LCOV - code coverage report
Current view: top level - gcc - ira-emit.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.8 % 692 649
Test Date: 2024-03-23 14:05:01 Functions: 83.9 % 31 26
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Integrated Register Allocator.  Changing code and generating moves.
       2                 :             :    Copyright (C) 2006-2024 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                 :     1419736 : ira_initiate_emit_data (void)
     102                 :             : {
     103                 :     1419736 :   ira_allocno_t a;
     104                 :     1419736 :   ira_allocno_iterator ai;
     105                 :             : 
     106                 :     1419736 :   ira_allocno_emit_data
     107                 :     1419736 :     = (ira_emit_data_t) ira_allocate (ira_allocnos_num
     108                 :             :                                       * sizeof (struct ira_emit_data));
     109                 :     1419736 :   memset (ira_allocno_emit_data, 0,
     110                 :     1419736 :           ira_allocnos_num * sizeof (struct ira_emit_data));
     111                 :    37334162 :   FOR_EACH_ALLOCNO (a, ai)
     112                 :    35914426 :     ALLOCNO_ADD_DATA (a) = ira_allocno_emit_data + ALLOCNO_NUM (a);
     113                 :     1419736 :   new_allocno_emit_data_vec.create (50);
     114                 :             : 
     115                 :     1419736 : }
     116                 :             : 
     117                 :             : /* Free the emit data.  */
     118                 :             : void
     119                 :     1419736 : ira_finish_emit_data (void)
     120                 :             : {
     121                 :     1419736 :   void_p p;
     122                 :     1419736 :   ira_allocno_t a;
     123                 :     1419736 :   ira_allocno_iterator ai;
     124                 :             : 
     125                 :     1419736 :   ira_free (ira_allocno_emit_data);
     126                 :    37337736 :   FOR_EACH_ALLOCNO (a, ai)
     127                 :    35918000 :     ALLOCNO_ADD_DATA (a) = NULL;
     128                 :     1423310 :   for (;new_allocno_emit_data_vec.length () != 0;)
     129                 :             :     {
     130                 :        3574 :       p = new_allocno_emit_data_vec.pop ();
     131                 :        3574 :       ira_free (p);
     132                 :             :     }
     133                 :     1419736 :   new_allocno_emit_data_vec.release ();
     134                 :     1419736 : }
     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                 :        3574 : create_new_allocno (int regno, ira_loop_tree_node_t loop_tree_node)
     140                 :             : {
     141                 :        3574 :   ira_allocno_t a;
     142                 :             : 
     143                 :        3574 :   a = ira_create_allocno (regno, false, loop_tree_node);
     144                 :        3574 :   ALLOCNO_ADD_DATA (a) = ira_allocate (sizeof (struct ira_emit_data));
     145                 :        3574 :   memset (ALLOCNO_ADD_DATA (a), 0, sizeof (struct ira_emit_data));
     146                 :        3574 :   new_allocno_emit_data_vec.safe_push (ALLOCNO_ADD_DATA (a));
     147                 :        3574 :   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                 :     1892335 : create_move (ira_allocno_t to, ira_allocno_t from)
     189                 :             : {
     190                 :     1892335 :   move_t move;
     191                 :             : 
     192                 :     1892335 :   move = (move_t) ira_allocate (sizeof (struct move));
     193                 :     1892335 :   move->deps = NULL;
     194                 :     1892335 :   move->deps_num = 0;
     195                 :     1892335 :   move->to = to;
     196                 :     1892335 :   move->from = from;
     197                 :     1892335 :   move->next = NULL;
     198                 :     1892335 :   move->insn = NULL;
     199                 :     1892335 :   move->visited_p = false;
     200                 :     1892335 :   return move;
     201                 :             : }
     202                 :             : 
     203                 :             : /* Free memory for MOVE and its dependencies.  */
     204                 :             : static void
     205                 :     1892335 : free_move (move_t move)
     206                 :             : {
     207                 :     1892335 :   if (move->deps != NULL)
     208                 :     1741555 :     ira_free (move->deps);
     209                 :     1892335 :   ira_free (move);
     210                 :     1892335 : }
     211                 :             : 
     212                 :             : /* Free memory for list of the moves given by its HEAD.  */
     213                 :             : static void
     214                 :    10302493 : free_move_list (move_t head)
     215                 :             : {
     216                 :    10302493 :   move_t next;
     217                 :             : 
     218                 :    12194828 :   for (; head != NULL; head = next)
     219                 :             :     {
     220                 :     1892335 :       next = head->next;
     221                 :     1892335 :       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                 :     2748853 : eq_move_lists_p (move_t list1, move_t list2)
     229                 :             : {
     230                 :     2853696 :   for (; list1 != NULL && list2 != NULL;
     231                 :      104843 :        list1 = list1->next, list2 = list2->next)
     232                 :      106636 :     if (list1->from != list2->from || list1->to != list2->to)
     233                 :             :       return false;
     234                 :     2747060 :   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                 :   192310043 : change_regs (rtx *loc)
     261                 :             : {
     262                 :   192310043 :   int i, regno, result = false;
     263                 :   192310043 :   const char *fmt;
     264                 :   192310043 :   enum rtx_code code;
     265                 :   192310043 :   rtx reg;
     266                 :             : 
     267                 :   192310043 :   if (*loc == NULL_RTX)
     268                 :             :     return false;
     269                 :   167384318 :   code = GET_CODE (*loc);
     270                 :   167384318 :   if (code == REG)
     271                 :             :     {
     272                 :    42540632 :       regno = REGNO (*loc);
     273                 :    42540632 :       if (regno < FIRST_PSEUDO_REGISTER)
     274                 :             :         return false;
     275                 :    23048083 :       if (regno >= max_regno_before_changing)
     276                 :             :         /* It is a shared register which was changed already.  */
     277                 :             :         return false;
     278                 :    23047965 :       if (ira_curr_regno_allocno_map[regno] == NULL)
     279                 :             :         return false;
     280                 :    23039158 :       reg = allocno_emit_reg (ira_curr_regno_allocno_map[regno]);
     281                 :    23039158 :       if (reg == *loc)
     282                 :             :         return false;
     283                 :     2663237 :       *loc = reg;
     284                 :     2663237 :       return true;
     285                 :             :     }
     286                 :             : 
     287                 :   124843686 :   fmt = GET_RTX_FORMAT (code);
     288                 :   455291916 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     289                 :             :     {
     290                 :   330448230 :       if (fmt[i] == 'e')
     291                 :   169949072 :         result = change_regs (&XEXP (*loc, i)) || result;
     292                 :   168806387 :       else if (fmt[i] == 'E')
     293                 :             :         {
     294                 :     3047812 :           int j;
     295                 :             : 
     296                 :     9668375 :           for (j = XVECLEN (*loc, i) - 1; j >= 0; j--)
     297                 :     7094150 :             result = change_regs (&XVECEXP (*loc, i, j)) || result;
     298                 :             :         }
     299                 :             :     }
     300                 :   124843686 :   return result;
     301                 :             : }
     302                 :             : 
     303                 :             : static bool
     304                 :    24047637 : change_regs_in_insn (rtx_insn **insn_ptr)
     305                 :             : {
     306                 :    24047637 :   rtx rtx = *insn_ptr;
     307                 :    24047637 :   bool result = change_regs (&rtx);
     308                 :    24047637 :   *insn_ptr = as_a <rtx_insn *> (rtx);
     309                 :    24047637 :   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                 :     1888761 : add_to_edge_list (edge e, move_t move, bool head_p)
     316                 :             : {
     317                 :     1888761 :   move_t last;
     318                 :             : 
     319                 :           0 :   if (head_p || e->aux == NULL)
     320                 :             :     {
     321                 :     1888761 :       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                 :     1025343 : ira_create_new_reg (rtx original_reg)
     337                 :             : {
     338                 :     1025343 :   rtx new_reg;
     339                 :             : 
     340                 :     1025343 :   new_reg = gen_reg_rtx (GET_MODE (original_reg));
     341                 :     1025343 :   ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original_reg);
     342                 :     1025343 :   REG_USERVAR_P (new_reg) = REG_USERVAR_P (original_reg);
     343                 :     1025343 :   REG_POINTER (new_reg) = REG_POINTER (original_reg);
     344                 :     1025343 :   REG_ATTRS (new_reg) = REG_ATTRS (original_reg);
     345                 :     1025343 :   if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
     346                 :           0 :     fprintf (ira_dump_file, "      Creating newreg=%i from oldreg=%i\n",
     347                 :             :              REGNO (new_reg), REGNO (original_reg));
     348                 :     1025343 :   ira_expand_reg_equiv ();
     349                 :     1025343 :   return new_reg;
     350                 :             : }
     351                 :             : 
     352                 :             : /* Return TRUE if loop given by SUBNODE inside the loop given by
     353                 :             :    NODE.  */
     354                 :             : static bool
     355                 :     6631696 : subloop_tree_node_p (ira_loop_tree_node_t subnode, ira_loop_tree_node_t node)
     356                 :             : {
     357                 :    20709486 :   for (; subnode != NULL; subnode = subnode->parent)
     358                 :    15637569 :     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                 :     1008137 : set_allocno_reg (ira_allocno_t allocno, rtx reg)
     367                 :             : {
     368                 :     1008137 :   int regno;
     369                 :     1008137 :   ira_allocno_t a;
     370                 :     1008137 :   ira_loop_tree_node_t node;
     371                 :             : 
     372                 :     1008137 :   node = ALLOCNO_LOOP_TREE_NODE (allocno);
     373                 :     1008137 :   for (a = ira_regno_allocno_map[ALLOCNO_REGNO (allocno)];
     374                 :     7639833 :        a != NULL;
     375                 :     6631696 :        a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
     376                 :    13263392 :     if (subloop_tree_node_p (ALLOCNO_LOOP_TREE_NODE (a), node))
     377                 :     1559779 :       ALLOCNO_EMIT_DATA (a)->reg = reg;
     378                 :     1009958 :   for (a = ALLOCNO_CAP (allocno); a != NULL; a = ALLOCNO_CAP (a))
     379                 :        1821 :     ALLOCNO_EMIT_DATA (a)->reg = reg;
     380                 :             :   regno = ALLOCNO_REGNO (allocno);
     381                 :             :   for (a = allocno;;)
     382                 :             :     {
     383                 :     2279065 :       if (a == NULL || (a = ALLOCNO_CAP (a)) == NULL)
     384                 :             :         {
     385                 :     2014192 :           node = node->parent;
     386                 :     2014192 :           if (node == NULL)
     387                 :             :             break;
     388                 :     1475277 :           a = node->regno_allocno_map[regno];
     389                 :             :         }
     390                 :     1740150 :       if (a == NULL)
     391                 :      263103 :         continue;
     392                 :     1477047 :       if (ALLOCNO_EMIT_DATA (a)->child_renamed_p)
     393                 :             :         break;
     394                 :     1007825 :       ALLOCNO_EMIT_DATA (a)->child_renamed_p = true;
     395                 :             :     }
     396                 :     1008137 : }
     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                 :      183621 : entered_from_non_parent_p (ira_loop_tree_node_t loop_node)
     403                 :             : {
     404                 :      183621 :   ira_loop_tree_node_t bb_node, src_loop_node, parent;
     405                 :      183621 :   edge e;
     406                 :      183621 :   edge_iterator ei;
     407                 :             : 
     408                 :      183621 :   for (bb_node = loop_node->children;
     409                 :     2941995 :        bb_node != NULL;
     410                 :     2758374 :        bb_node = bb_node->next)
     411                 :     2759140 :     if (bb_node->bb != NULL)
     412                 :             :       {
     413                 :     6574241 :         FOR_EACH_EDGE (e, ei, bb_node->bb->preds)
     414                 :     3964632 :           if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
     415                 :     3964632 :               && (src_loop_node = IRA_BB_NODE (e->src)->parent) != loop_node)
     416                 :             :             {
     417                 :      432396 :               for (parent = src_loop_node->parent;
     418                 :      561700 :                    parent != NULL;
     419                 :      129304 :                    parent = parent->parent)
     420                 :      392519 :                 if (parent == loop_node)
     421                 :             :                   break;
     422                 :      432396 :               if (parent != NULL)
     423                 :             :                 /* That is an exit from a nested loop -- skip it.  */
     424                 :      263215 :                 continue;
     425                 :      169181 :               for (parent = loop_node->parent;
     426                 :      170660 :                    parent != NULL;
     427                 :        1479 :                    parent = parent->parent)
     428                 :      169894 :                 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                 :       34829 : setup_entered_from_non_parent_p (void)
     440                 :             : {
     441                 :       34829 :   unsigned int i;
     442                 :       34829 :   loop_p loop;
     443                 :             : 
     444                 :       34829 :   ira_assert (current_loops != NULL);
     445                 :      233989 :   FOR_EACH_VEC_SAFE_ELT (get_loops (cfun), i, loop)
     446                 :      199160 :     if (ira_loop_nodes[i].regno_allocno_map != NULL)
     447                 :      183621 :       ira_loop_nodes[i].entered_from_non_parent_p
     448                 :      183621 :         = entered_from_non_parent_p (&ira_loop_nodes[i]);
     449                 :       34829 : }
     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                 :      114561 : store_can_be_removed_p (ira_allocno_t src_allocno, ira_allocno_t dest_allocno)
     458                 :             : {
     459                 :      114561 :   int regno, orig_regno;
     460                 :      114561 :   ira_allocno_t a;
     461                 :      114561 :   ira_loop_tree_node_t node;
     462                 :             : 
     463                 :      114561 :   ira_assert (ALLOCNO_CAP_MEMBER (src_allocno) == NULL
     464                 :             :               && ALLOCNO_CAP_MEMBER (dest_allocno) == NULL);
     465                 :      114561 :   orig_regno = ALLOCNO_REGNO (src_allocno);
     466                 :      114561 :   regno = REGNO (allocno_emit_reg (dest_allocno));
     467                 :      114561 :   for (node = ALLOCNO_LOOP_TREE_NODE (src_allocno);
     468                 :      159947 :        node != NULL;
     469                 :       45386 :        node = node->parent)
     470                 :             :     {
     471                 :      159947 :       a = node->regno_allocno_map[orig_regno];
     472                 :      159947 :       ira_assert (a != NULL);
     473                 :      159947 :       if (REGNO (allocno_emit_reg (a)) == (unsigned) regno)
     474                 :             :         /* We achieved the destination and everything is ok.  */
     475                 :             :         return true;
     476                 :      136736 :       else if (bitmap_bit_p (node->modified_regnos, orig_regno))
     477                 :             :         return false;
     478                 :       45628 :       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                 :     3931350 : generate_edge_moves (edge e)
     498                 :             : {
     499                 :     3931350 :   ira_loop_tree_node_t src_loop_node, dest_loop_node;
     500                 :     3931350 :   unsigned int regno;
     501                 :     3931350 :   bitmap_iterator bi;
     502                 :     3931350 :   ira_allocno_t src_allocno, dest_allocno, *src_map, *dest_map;
     503                 :     3931350 :   move_t move;
     504                 :     3931350 :   bitmap regs_live_in_dest, regs_live_out_src;
     505                 :             : 
     506                 :     3931350 :   src_loop_node = IRA_BB_NODE (e->src)->parent;
     507                 :     3931350 :   dest_loop_node = IRA_BB_NODE (e->dest)->parent;
     508                 :     3931350 :   e->aux = NULL;
     509                 :     3931350 :   if (src_loop_node == dest_loop_node)
     510                 :     3498065 :     return;
     511                 :      433285 :   src_map = src_loop_node->regno_allocno_map;
     512                 :      433285 :   dest_map = dest_loop_node->regno_allocno_map;
     513                 :      433285 :   regs_live_in_dest = df_get_live_in (e->dest);
     514                 :      433285 :   regs_live_out_src = df_get_live_out (e->src);
     515                 :     6363137 :   EXECUTE_IF_SET_IN_REG_SET (regs_live_in_dest,
     516                 :             :                              FIRST_PSEUDO_REGISTER, regno, bi)
     517                 :     5929852 :     if (bitmap_bit_p (regs_live_out_src, regno))
     518                 :             :       {
     519                 :     5929852 :         src_allocno = src_map[regno];
     520                 :     5929852 :         dest_allocno = dest_map[regno];
     521                 :     5929852 :         if (REGNO (allocno_emit_reg (src_allocno))
     522                 :     5929852 :             == REGNO (allocno_emit_reg (dest_allocno)))
     523                 :     4017880 :           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                 :     1935183 :         if (ALLOCNO_HARD_REGNO (dest_allocno) < 0
     529                 :      114736 :             && ALLOCNO_HARD_REGNO (src_allocno) >= 0
     530                 :     2026533 :             && store_can_be_removed_p (src_allocno, dest_allocno))
     531                 :             :           {
     532                 :       23211 :             ALLOCNO_EMIT_DATA (src_allocno)->mem_optimized_dest = dest_allocno;
     533                 :       23211 :             ALLOCNO_EMIT_DATA (dest_allocno)->mem_optimized_dest_p = true;
     534                 :       23211 :             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                 :       23211 :             continue;
     539                 :             :           }
     540                 :     1888761 :         move = create_move (dest_allocno, src_allocno);
     541                 :     1888761 :         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                 :     2794166 : change_loop (ira_loop_tree_node_t node)
     562                 :             : {
     563                 :     2794166 :   bitmap_iterator bi;
     564                 :     2794166 :   unsigned int i;
     565                 :     2794166 :   int regno;
     566                 :     2794166 :   bool used_p;
     567                 :     2794166 :   ira_allocno_t allocno, parent_allocno, *map;
     568                 :     2794166 :   rtx_insn *insn;
     569                 :     2794166 :   rtx original_reg;
     570                 :     2794166 :   enum reg_class aclass, pclass;
     571                 :     2794166 :   ira_loop_tree_node_t parent;
     572                 :             : 
     573                 :     2794166 :   if (node != ira_loop_tree_root)
     574                 :             :     {
     575                 :     2759337 :       ira_assert (current_loops != NULL);
     576                 :             :       
     577                 :     2759337 :       if (node->bb != NULL)
     578                 :             :         {
     579                 :    31459814 :           FOR_BB_INSNS (node->bb, insn)
     580                 :    28849269 :             if (INSN_P (insn) && change_regs_in_insn (&insn))
     581                 :             :               {
     582                 :     1787528 :                 df_insn_rescan (insn);
     583                 :     1787528 :                 df_notes_rescan (insn);
     584                 :             :               }
     585                 :     2610545 :           return;
     586                 :             :         }
     587                 :             : 
     588                 :      148792 :       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                 :      148792 :       parent = ira_curr_loop_tree_node->parent;
     594                 :      148792 :       map = parent->regno_allocno_map;
     595                 :     2923050 :       EXECUTE_IF_SET_IN_REG_SET (ira_curr_loop_tree_node->border_allocnos,
     596                 :             :                                  0, i, bi)
     597                 :             :         {
     598                 :     2774258 :           allocno = ira_allocnos[i];
     599                 :     2774258 :           regno = ALLOCNO_REGNO (allocno);
     600                 :     2774258 :           aclass = ALLOCNO_CLASS (allocno);
     601                 :     2774258 :           pclass = ira_pressure_class_translate[aclass];
     602                 :     2774258 :           parent_allocno = map[regno];
     603                 :     2774258 :           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                 :     4541756 :           if (parent_allocno != NULL
     611                 :     2774258 :               && (ALLOCNO_HARD_REGNO (allocno)
     612                 :     2774258 :                   == ALLOCNO_HARD_REGNO (parent_allocno))
     613                 :     5376234 :               && (ALLOCNO_HARD_REGNO (allocno) < 0
     614                 :      992450 :                   || (parent->reg_pressure[pclass] + 1
     615                 :      992450 :                       <= ira_class_hard_regs_num[pclass])
     616                 :      923989 :                   || TEST_HARD_REG_BIT (ira_prohibited_mode_move_regs
     617                 :      923989 :                                         [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                 :      923989 :                   || ira_equiv_no_lvalue_p (regno)
     623                 :      841208 :                   || (pic_offset_table_rtx != NULL
     624                 :       78488 :                       && (ALLOCNO_REGNO (allocno)
     625                 :       78488 :                           == (int) REGNO (pic_offset_table_rtx)))))
     626                 :     1767498 :             continue;
     627                 :     1006760 :           original_reg = allocno_emit_reg (allocno);
     628                 :     1006760 :           if (parent_allocno == NULL
     629                 :     1006760 :               || (REGNO (allocno_emit_reg (parent_allocno))
     630                 :     1006760 :                   == REGNO (original_reg)))
     631                 :             :             {
     632                 :     1006760 :               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                 :     1006760 :               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                 :      183621 :   bitmap_and_compl (local_allocno_bitmap,
     644                 :      183621 :                     ira_curr_loop_tree_node->all_allocnos,
     645                 :      183621 :                     ira_curr_loop_tree_node->border_allocnos);
     646                 :     8568599 :   EXECUTE_IF_SET_IN_REG_SET (local_allocno_bitmap, 0, i, bi)
     647                 :             :     {
     648                 :     8384978 :       allocno = ira_allocnos[i];
     649                 :     8384978 :       regno = ALLOCNO_REGNO (allocno);
     650                 :     8384978 :       if (ALLOCNO_CAP_MEMBER (allocno) != NULL)
     651                 :     3640187 :         continue;
     652                 :     4744791 :       used_p = !bitmap_set_bit (used_regno_bitmap, regno);
     653                 :     4744791 :       ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
     654                 :     4744791 :       if (! used_p)
     655                 :     4743414 :         continue;
     656                 :        1377 :       bitmap_set_bit (renamed_regno_bitmap, regno);
     657                 :        1377 :       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                 :       34829 : set_allocno_somewhere_renamed_p (void)
     664                 :             : {
     665                 :       34829 :   unsigned int regno;
     666                 :       34829 :   ira_allocno_t allocno;
     667                 :       34829 :   ira_allocno_iterator ai;
     668                 :             : 
     669                 :    11194065 :   FOR_EACH_ALLOCNO (allocno, ai)
     670                 :             :     {
     671                 :    11159236 :       regno = ALLOCNO_REGNO (allocno);
     672                 :    11159236 :       if (bitmap_bit_p (renamed_regno_bitmap, regno)
     673                 :    11159236 :           && REGNO (allocno_emit_reg (allocno)) == regno)
     674                 :        1730 :         ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
     675                 :             :     }
     676                 :       34829 : }
     677                 :             : 
     678                 :             : /* Return TRUE if move lists on all edges given in vector VEC are
     679                 :             :    equal.  */
     680                 :             : static bool
     681                 :     5142148 : eq_edge_move_lists_p (vec<edge, va_gc> *vec)
     682                 :             : {
     683                 :     5142148 :   move_t list;
     684                 :     5142148 :   int i;
     685                 :             : 
     686                 :     5142148 :   list = (move_t) EDGE_I (vec, 0)->aux;
     687                 :     7629391 :   for (i = EDGE_COUNT (vec) - 1; i > 0; i--)
     688                 :     2748853 :     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                 :     5221090 : unify_moves (basic_block bb, bool start_p)
     698                 :             : {
     699                 :     5221090 :   int i;
     700                 :     5221090 :   edge e;
     701                 :     5221090 :   move_t list;
     702                 :     5221090 :   vec<edge, va_gc> *vec;
     703                 :             : 
     704                 :     5221090 :   vec = (start_p ? bb->preds : bb->succs);
     705                 :     5221090 :   if (EDGE_COUNT (vec) == 0 || ! eq_edge_move_lists_p (vec))
     706                 :             :     return;
     707                 :     4880538 :   e = EDGE_I (vec, 0);
     708                 :     4880538 :   list = (move_t) e->aux;
     709                 :     4880538 :   if (! start_p && control_flow_insn_p (BB_END (bb)))
     710                 :             :     return;
     711                 :     2889841 :   e->aux = NULL;
     712                 :     4002714 :   for (i = EDGE_COUNT (vec) - 1; i > 0; i--)
     713                 :             :     {
     714                 :     1112873 :       e = EDGE_I (vec, i);
     715                 :     1112873 :       free_move_list ((move_t) e->aux);
     716                 :     1112873 :       e->aux = NULL;
     717                 :             :     }
     718                 :     2889841 :   if (start_p)
     719                 :     2434566 :     at_bb_start[bb->index] = list;
     720                 :             :   else
     721                 :      455275 :     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                 :     1933215 : traverse_moves (move_t move)
     755                 :             : {
     756                 :     1933215 :   int i;
     757                 :             : 
     758                 :     1933215 :   if (move->visited_p)
     759                 :             :     return;
     760                 :     1867863 :   move->visited_p = true;
     761                 :     1933215 :   for (i = move->deps_num - 1; i >= 0; i--)
     762                 :       65352 :     traverse_moves (move->deps[i]);
     763                 :     1867863 :   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                 :      339494 : modify_move_list (move_t list)
     772                 :             : {
     773                 :      339494 :   int i, n, nregs, hard_regno;
     774                 :      339494 :   ira_allocno_t to, from;
     775                 :      339494 :   move_t move, new_move, set_move, first, last;
     776                 :             : 
     777                 :      339494 :   if (list == NULL)
     778                 :             :     return NULL;
     779                 :             :   /* Create move deps.  */
     780                 :      339494 :   curr_tick++;
     781                 :     2207357 :   for (move = list; move != NULL; move = move->next)
     782                 :             :     {
     783                 :     1867863 :       to = move->to;
     784                 :     1867863 :       if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
     785                 :       90821 :         continue;
     786                 :     1777042 :       nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (to));
     787                 :     3566965 :       for (i = 0; i < nregs; i++)
     788                 :             :         {
     789                 :     1789923 :           hard_regno_last_set[hard_regno + i] = move;
     790                 :     1789923 :           hard_regno_last_set_check[hard_regno + i] = curr_tick;
     791                 :             :         }
     792                 :             :     }
     793                 :     2207357 :   for (move = list; move != NULL; move = move->next)
     794                 :             :     {
     795                 :     1867863 :       from = move->from;
     796                 :     1867863 :       to = move->to;
     797                 :     1867863 :       if ((hard_regno = ALLOCNO_HARD_REGNO (from)) >= 0)
     798                 :             :         {
     799                 :     1741555 :           nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (from));
     800                 :     3494122 :           for (n = i = 0; i < nregs; i++)
     801                 :     1752567 :             if (hard_regno_last_set_check[hard_regno + i] == curr_tick
     802                 :     1635889 :                 && (ALLOCNO_REGNO (hard_regno_last_set[hard_regno + i]->to)
     803                 :     1635889 :                     != ALLOCNO_REGNO (from)))
     804                 :       65352 :               n++;
     805                 :     1741555 :           move->deps = (move_t *) ira_allocate (n * sizeof (move_t));
     806                 :     3494122 :           for (n = i = 0; i < nregs; i++)
     807                 :     1752567 :             if (hard_regno_last_set_check[hard_regno + i] == curr_tick
     808                 :     1635889 :                 && (ALLOCNO_REGNO (hard_regno_last_set[hard_regno + i]->to)
     809                 :     1635889 :                     != ALLOCNO_REGNO (from)))
     810                 :       65352 :               move->deps[n++] = hard_regno_last_set[hard_regno + i];
     811                 :     1741555 :           move->deps_num = n;
     812                 :             :         }
     813                 :             :     }
     814                 :             :   /* Topological sorting:  */
     815                 :      339494 :   move_vec.truncate (0);
     816                 :     2546851 :   for (move = list; move != NULL; move = move->next)
     817                 :     1867863 :     traverse_moves (move);
     818                 :      339494 :   last = NULL;
     819                 :     2546851 :   for (i = (int) move_vec.length () - 1; i >= 0; i--)
     820                 :             :     {
     821                 :     1867863 :       move = move_vec[i];
     822                 :     1867863 :       move->next = NULL;
     823                 :     1867863 :       if (last != NULL)
     824                 :     1528369 :         last->next = move;
     825                 :     1867863 :       last = move;
     826                 :             :     }
     827                 :      339494 :   first = move_vec.last ();
     828                 :             :   /* Removing cycles:  */
     829                 :      339494 :   curr_tick++;
     830                 :      339494 :   move_vec.truncate (0);
     831                 :     2207357 :   for (move = first; move != NULL; move = move->next)
     832                 :             :     {
     833                 :     1867863 :       from = move->from;
     834                 :     1867863 :       to = move->to;
     835                 :     1867863 :       if ((hard_regno = ALLOCNO_HARD_REGNO (from)) >= 0)
     836                 :             :         {
     837                 :     1741555 :           nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (from));
     838                 :     3494122 :           for (i = 0; i < nregs; i++)
     839                 :     1752567 :             if (hard_regno_last_set_check[hard_regno + i] == curr_tick
     840                 :        3574 :                 && ALLOCNO_HARD_REGNO
     841                 :             :                    (hard_regno_last_set[hard_regno + i]->to) >= 0)
     842                 :             :               {
     843                 :        3574 :                 int n, j;
     844                 :        3574 :                 ira_allocno_t new_allocno;
     845                 :             : 
     846                 :        3574 :                 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                 :        3574 :                 new_allocno
     852                 :        3574 :                   = create_new_allocno (ALLOCNO_REGNO (set_move->to),
     853                 :             :                                         ALLOCNO_LOOP_TREE_NODE (set_move->to));
     854                 :        3574 :                 ALLOCNO_MODE (new_allocno) = ALLOCNO_MODE (set_move->to);
     855                 :        3574 :                 ira_set_allocno_class (new_allocno,
     856                 :        3574 :                                        ALLOCNO_CLASS (set_move->to));
     857                 :        3574 :                 ira_create_allocno_objects (new_allocno);
     858                 :        3574 :                 ALLOCNO_ASSIGNED_P (new_allocno) = true;
     859                 :        3574 :                 ALLOCNO_HARD_REGNO (new_allocno) = -1;
     860                 :        3574 :                 ALLOCNO_EMIT_DATA (new_allocno)->reg
     861                 :        3574 :                   = 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                 :        3574 :                 n = ALLOCNO_NUM_OBJECTS (new_allocno);
     867                 :        3574 :                 gcc_assert (n == ALLOCNO_NUM_OBJECTS (set_move->to));
     868                 :        7148 :                 for (j = 0; j < n; j++)
     869                 :             :                   {
     870                 :        3574 :                     ira_object_t new_obj = ALLOCNO_OBJECT (new_allocno, j);
     871                 :             : 
     872                 :        3574 :                     OBJECT_MIN (new_obj) = 0;
     873                 :        3574 :                     OBJECT_MAX (new_obj) = ira_objects_num - 1;
     874                 :             :                   }
     875                 :             : 
     876                 :        3574 :                 new_move = create_move (set_move->to, new_allocno);
     877                 :        3574 :                 set_move->to = new_allocno;
     878                 :        3574 :                 move_vec.safe_push (new_move);
     879                 :        3574 :                 ira_move_loops_num++;
     880                 :        3574 :                 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                 :     1867863 :       if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
     888                 :       90821 :         continue;
     889                 :     1777042 :       nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (to));
     890                 :     3566965 :       for (i = 0; i < nregs; i++)
     891                 :             :         {
     892                 :     1789923 :           hard_regno_last_set[hard_regno + i] = move;
     893                 :     1789923 :           hard_regno_last_set_check[hard_regno + i] = curr_tick;
     894                 :             :         }
     895                 :             :     }
     896                 :      682562 :   for (i = (int) move_vec.length () - 1; i >= 0; i--)
     897                 :             :     {
     898                 :        3574 :       move = move_vec[i];
     899                 :        3574 :       move->next = NULL;
     900                 :        3574 :       last->next = move;
     901                 :        3574 :       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                 :      339494 : emit_move_list (move_t list, int freq)
     910                 :             : {
     911                 :      339494 :   rtx to, from, dest;
     912                 :      339494 :   int to_regno, from_regno, cost, regno;
     913                 :      339494 :   rtx_insn *result, *insn;
     914                 :      339494 :   rtx set;
     915                 :      339494 :   machine_mode mode;
     916                 :      339494 :   enum reg_class aclass;
     917                 :             : 
     918                 :      339494 :   grow_reg_equivs ();
     919                 :      339494 :   start_sequence ();
     920                 :     2550425 :   for (; list != NULL; list = list->next)
     921                 :             :     {
     922                 :     1871437 :       start_sequence ();
     923                 :     1871437 :       to = allocno_emit_reg (list->to);
     924                 :     1871437 :       to_regno = REGNO (to);
     925                 :     1871437 :       from = allocno_emit_reg (list->from);
     926                 :     1871437 :       from_regno = REGNO (from);
     927                 :     1871437 :       emit_move_insn (to, from);
     928                 :     1871437 :       list->insn = get_insns ();
     929                 :     1871437 :       end_sequence ();
     930                 :     3742874 :       for (insn = list->insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
     931                 :             :         {
     932                 :             :           /* The reload needs to have set up insn codes.  If the
     933                 :             :              reload sets up insn codes by itself, it may fail because
     934                 :             :              insns will have hard registers instead of pseudos and
     935                 :             :              there may be no machine insn with given hard
     936                 :             :              registers.  */
     937                 :     1871437 :           recog_memoized (insn);
     938                 :             :           /* Add insn to equiv init insn list if it is necessary.
     939                 :             :              Otherwise reload will not remove this insn if it decides
     940                 :             :              to use the equivalence.  */
     941                 :     1871437 :           if ((set = single_set (insn)) != NULL_RTX)
     942                 :             :             {
     943                 :     1871437 :               dest = SET_DEST (set);
     944                 :     1871437 :               if (GET_CODE (dest) == SUBREG)
     945                 :           0 :                 dest = SUBREG_REG (dest);
     946                 :     1871437 :               ira_assert (REG_P (dest));
     947                 :     1871437 :               regno = REGNO (dest);
     948                 :     1871437 :               if (regno >= ira_reg_equiv_len
     949                 :     1871437 :                   || (ira_reg_equiv[regno].invariant == NULL_RTX
     950                 :     1871411 :                       && ira_reg_equiv[regno].constant == NULL_RTX))
     951                 :     1871380 :                 continue; /* regno has no equivalence.  */
     952                 :          57 :               ira_assert ((int) reg_equivs->length () > regno);
     953                 :          57 :               reg_equiv_init (regno)
     954                 :         114 :                 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init (regno));
     955                 :             :             }
     956                 :             :         }
     957                 :     1871437 :       if (ira_use_lra_p)
     958                 :     1871437 :         ira_update_equiv_info_by_shuffle_insn (to_regno, from_regno, list->insn);
     959                 :     1871437 :       emit_insn (list->insn);
     960                 :     1871437 :       mode = ALLOCNO_MODE (list->to);
     961                 :     1871437 :       aclass = ALLOCNO_CLASS (list->to);
     962                 :     1871437 :       cost = 0;
     963                 :     1871437 :       if (ALLOCNO_HARD_REGNO (list->to) < 0)
     964                 :             :         {
     965                 :       94395 :           if (ALLOCNO_HARD_REGNO (list->from) >= 0)
     966                 :             :             {
     967                 :       94228 :               cost = ira_memory_move_cost[mode][aclass][0] * freq;
     968                 :       94228 :               ira_store_cost += cost;
     969                 :             :             }
     970                 :             :         }
     971                 :     1777042 :       else if (ALLOCNO_HARD_REGNO (list->from) < 0)
     972                 :             :         {
     973                 :      129715 :           if (ALLOCNO_HARD_REGNO (list->to) >= 0)
     974                 :             :             {
     975                 :      129715 :               cost = ira_memory_move_cost[mode][aclass][0] * freq;
     976                 :      129715 :               ira_load_cost += cost;
     977                 :             :             }
     978                 :             :         }
     979                 :             :       else
     980                 :             :         {
     981                 :     1647327 :           ira_init_register_move_cost_if_necessary (mode);
     982                 :     1647327 :           cost = ira_register_move_cost[mode][aclass][aclass] * freq;
     983                 :     1647327 :           ira_shuffle_cost += cost;
     984                 :             :         }
     985                 :     1871437 :       ira_overall_cost += cost;
     986                 :             :     }
     987                 :      339494 :   result = get_insns ();
     988                 :      339494 :   end_sequence ();
     989                 :      339494 :   return result;
     990                 :             : }
     991                 :             : 
     992                 :             : /* Generate RTX move insns from move lists attached to basic blocks
     993                 :             :    and edges.  */
     994                 :             : static void
     995                 :       34829 : emit_moves (void)
     996                 :             : {
     997                 :       34829 :   basic_block bb;
     998                 :       34829 :   edge_iterator ei;
     999                 :       34829 :   edge e;
    1000                 :       34829 :   rtx_insn *insns, *tmp, *next;
    1001                 :             : 
    1002                 :     2645374 :   FOR_EACH_BB_FN (bb, cfun)
    1003                 :             :     {
    1004                 :     2610545 :       if (at_bb_start[bb->index] != NULL)
    1005                 :             :         {
    1006                 :      134816 :           at_bb_start[bb->index] = modify_move_list (at_bb_start[bb->index]);
    1007                 :      134816 :           insns
    1008                 :      134816 :             = emit_move_list (at_bb_start[bb->index], REG_FREQ_FROM_BB (bb));
    1009                 :      134816 :           tmp = BB_HEAD (bb);
    1010                 :      134816 :           if (LABEL_P (tmp))
    1011                 :       23654 :             tmp = NEXT_INSN (tmp);
    1012                 :      134816 :           if (NOTE_INSN_BASIC_BLOCK_P (tmp))
    1013                 :      134816 :             tmp = NEXT_INSN (tmp);
    1014                 :             :           /* Make sure to put the location of TMP or a subsequent instruction
    1015                 :             :              to avoid inheriting the location of the previous instruction.  */
    1016                 :      134816 :           next = tmp;
    1017                 :      264129 :           while (next && !NONDEBUG_INSN_P (next))
    1018                 :      129313 :             next = NEXT_INSN (next);
    1019                 :      134816 :           if (next)
    1020                 :      134816 :             set_insn_locations (insns, INSN_LOCATION (next));
    1021                 :      134816 :           if (tmp == BB_HEAD (bb))
    1022                 :           0 :             emit_insn_before (insns, tmp);
    1023                 :      134816 :           else if (tmp)
    1024                 :      134816 :             emit_insn_after (insns, PREV_INSN (tmp));
    1025                 :             :           else
    1026                 :           0 :             emit_insn_after (insns, get_last_insn ());
    1027                 :             :         }
    1028                 :             : 
    1029                 :     2610545 :       if (at_bb_end[bb->index] != NULL)
    1030                 :             :         {
    1031                 :       86878 :           at_bb_end[bb->index] = modify_move_list (at_bb_end[bb->index]);
    1032                 :       86878 :           insns = emit_move_list (at_bb_end[bb->index], REG_FREQ_FROM_BB (bb));
    1033                 :       86878 :           ira_assert (! control_flow_insn_p (BB_END (bb)));
    1034                 :       86878 :           emit_insn_after (insns, BB_END (bb));
    1035                 :             :         }
    1036                 :             : 
    1037                 :     6579075 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1038                 :             :         {
    1039                 :     3968530 :           if (e->aux == NULL)
    1040                 :     3850730 :             continue;
    1041                 :      117800 :           ira_assert ((e->flags & EDGE_ABNORMAL) == 0
    1042                 :             :                       || ! EDGE_CRITICAL_P (e));
    1043                 :      117800 :           e->aux = modify_move_list ((move_t) e->aux);
    1044                 :      117800 :           insert_insn_on_edge
    1045                 :      235548 :             (emit_move_list ((move_t) e->aux,
    1046                 :      235548 :                              REG_FREQ_FROM_EDGE_FREQ (EDGE_FREQUENCY (e))),
    1047                 :             :              e);
    1048                 :      117800 :           if (e->src->next_bb != e->dest)
    1049                 :       87883 :             ira_additional_jumps_num++;
    1050                 :             :         }
    1051                 :             :     }
    1052                 :       34829 : }
    1053                 :             : 
    1054                 :             : /* Update costs of A and corresponding allocnos on upper levels on the
    1055                 :             :    loop tree from reading (if READ_P) or writing A on an execution
    1056                 :             :    path with FREQ.  */
    1057                 :             : static void
    1058                 :     3742874 : update_costs (ira_allocno_t a, bool read_p, int freq)
    1059                 :             : {
    1060                 :     8903601 :   ira_loop_tree_node_t parent;
    1061                 :             : 
    1062                 :     8903601 :   for (;;)
    1063                 :             :     {
    1064                 :     8903601 :       ALLOCNO_NREFS (a)++;
    1065                 :     8903601 :       ALLOCNO_FREQ (a) += freq;
    1066                 :     8903601 :       ALLOCNO_MEMORY_COST (a)
    1067                 :    17807202 :         += (ira_memory_move_cost[ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)]
    1068                 :     8903601 :             [read_p ? 1 : 0] * freq);
    1069                 :     8903601 :       if (ALLOCNO_CAP (a) != NULL)
    1070                 :             :         a = ALLOCNO_CAP (a);
    1071                 :     7527439 :       else if ((parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL
    1072                 :     7527439 :                || (a = parent->regno_allocno_map[ALLOCNO_REGNO (a)]) == NULL)
    1073                 :             :         break;
    1074                 :             :     }
    1075                 :     3742874 : }
    1076                 :             : 
    1077                 :             : /* Process moves from LIST with execution FREQ to add ranges, copies,
    1078                 :             :    and modify costs for allocnos involved in the moves.  All regnos
    1079                 :             :    living through the list is in LIVE_THROUGH, and the loop tree node
    1080                 :             :    used to find corresponding allocnos is NODE.  */
    1081                 :             : static void
    1082                 :     9189620 : add_range_and_copies_from_move_list (move_t list, ira_loop_tree_node_t node,
    1083                 :             :                                      bitmap live_through, int freq)
    1084                 :             : {
    1085                 :     9189620 :   int start, n;
    1086                 :     9189620 :   unsigned int regno;
    1087                 :     9189620 :   move_t move;
    1088                 :     9189620 :   ira_allocno_t a;
    1089                 :     9189620 :   ira_copy_t cp;
    1090                 :     9189620 :   live_range_t r;
    1091                 :     9189620 :   bitmap_iterator bi;
    1092                 :     9189620 :   HARD_REG_SET hard_regs_live;
    1093                 :             : 
    1094                 :     9189620 :   if (list == NULL)
    1095                 :     8850126 :     return;
    1096                 :      339494 :   n = 0;
    1097                 :     6022044 :   EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
    1098                 :     5682550 :     n++;
    1099                 :      339494 :   REG_SET_TO_HARD_REG_SET (hard_regs_live, live_through);
    1100                 :             :   /* This is a trick to guarantee that new ranges is not merged with
    1101                 :             :      the old ones.  */
    1102                 :      339494 :   ira_max_point++;
    1103                 :      339494 :   start = ira_max_point;
    1104                 :     2210931 :   for (move = list; move != NULL; move = move->next)
    1105                 :             :     {
    1106                 :     1871437 :       ira_allocno_t from = move->from;
    1107                 :     1871437 :       ira_allocno_t to = move->to;
    1108                 :     1871437 :       int nr, i;
    1109                 :             : 
    1110                 :     1871437 :       bitmap_clear_bit (live_through, ALLOCNO_REGNO (from));
    1111                 :     1871437 :       bitmap_clear_bit (live_through, ALLOCNO_REGNO (to));
    1112                 :             : 
    1113                 :     1871437 :       nr = ALLOCNO_NUM_OBJECTS (to);
    1114                 :     3757127 :       for (i = 0; i < nr; i++)
    1115                 :             :         {
    1116                 :     1885690 :           ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
    1117                 :     1885690 :           if (OBJECT_CONFLICT_ARRAY (to_obj) == NULL)
    1118                 :             :             {
    1119                 :        3574 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1120                 :           0 :                 fprintf (ira_dump_file, "    Allocate conflicts for a%dr%d\n",
    1121                 :           0 :                          ALLOCNO_NUM (to), REGNO (allocno_emit_reg (to)));
    1122                 :        3574 :               ira_allocate_object_conflicts (to_obj, n);
    1123                 :             :             }
    1124                 :             :         }
    1125                 :     1871437 :       ior_hard_reg_conflicts (from, hard_regs_live);
    1126                 :     1871437 :       ior_hard_reg_conflicts (to, hard_regs_live);
    1127                 :             : 
    1128                 :     1871437 :       update_costs (from, true, freq);
    1129                 :     1871437 :       update_costs (to, false, freq);
    1130                 :     1871437 :       cp = ira_add_allocno_copy (from, to, freq, false, move->insn, NULL);
    1131                 :     1871437 :       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1132                 :           0 :         fprintf (ira_dump_file, "    Adding cp%d:a%dr%d-a%dr%d\n",
    1133                 :             :                  cp->num, ALLOCNO_NUM (cp->first),
    1134                 :           0 :                  REGNO (allocno_emit_reg (cp->first)),
    1135                 :             :                  ALLOCNO_NUM (cp->second),
    1136                 :           0 :                  REGNO (allocno_emit_reg (cp->second)));
    1137                 :             : 
    1138                 :     1871437 :       nr = ALLOCNO_NUM_OBJECTS (from);
    1139                 :     3757127 :       for (i = 0; i < nr; i++)
    1140                 :             :         {
    1141                 :     1885690 :           ira_object_t from_obj = ALLOCNO_OBJECT (from, i);
    1142                 :     1885690 :           r = OBJECT_LIVE_RANGES (from_obj);
    1143                 :     1885690 :           if (r == NULL || r->finish >= 0)
    1144                 :             :             {
    1145                 :     1882116 :               ira_add_live_range_to_object (from_obj, start, ira_max_point);
    1146                 :     1882116 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1147                 :           0 :                 fprintf (ira_dump_file,
    1148                 :             :                          "    Adding range [%d..%d] to allocno a%dr%d\n",
    1149                 :             :                          start, ira_max_point, ALLOCNO_NUM (from),
    1150                 :           0 :                          REGNO (allocno_emit_reg (from)));
    1151                 :             :             }
    1152                 :             :           else
    1153                 :             :             {
    1154                 :        3574 :               r->finish = ira_max_point;
    1155                 :        3574 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1156                 :           0 :                 fprintf (ira_dump_file,
    1157                 :             :                          "    Adding range [%d..%d] to allocno a%dr%d\n",
    1158                 :             :                          r->start, ira_max_point, ALLOCNO_NUM (from),
    1159                 :           0 :                          REGNO (allocno_emit_reg (from)));
    1160                 :             :             }
    1161                 :             :         }
    1162                 :     1871437 :       ira_max_point++;
    1163                 :     1871437 :       nr = ALLOCNO_NUM_OBJECTS (to);
    1164                 :     3757127 :       for (i = 0; i < nr; i++)
    1165                 :             :         {
    1166                 :     1885690 :           ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
    1167                 :     1885690 :           ira_add_live_range_to_object (to_obj, ira_max_point, -1);
    1168                 :             :         }
    1169                 :     1871437 :       ira_max_point++;
    1170                 :             :     }
    1171                 :     2210931 :   for (move = list; move != NULL; move = move->next)
    1172                 :             :     {
    1173                 :     1871437 :       int nr, i;
    1174                 :     1871437 :       nr = ALLOCNO_NUM_OBJECTS (move->to);
    1175                 :     3757127 :       for (i = 0; i < nr; i++)
    1176                 :             :         {
    1177                 :     1885690 :           ira_object_t to_obj = ALLOCNO_OBJECT (move->to, i);
    1178                 :     1885690 :           r = OBJECT_LIVE_RANGES (to_obj);
    1179                 :     1885690 :           if (r->finish < 0)
    1180                 :             :             {
    1181                 :     1882116 :               r->finish = ira_max_point - 1;
    1182                 :     1882116 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1183                 :           0 :                 fprintf (ira_dump_file,
    1184                 :             :                          "    Adding range [%d..%d] to allocno a%dr%d\n",
    1185                 :             :                          r->start, r->finish, ALLOCNO_NUM (move->to),
    1186                 :           0 :                          REGNO (allocno_emit_reg (move->to)));
    1187                 :             :             }
    1188                 :             :         }
    1189                 :             :     }
    1190                 :     4154181 :   EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
    1191                 :             :     {
    1192                 :     3814687 :       ira_allocno_t to;
    1193                 :     3814687 :       int nr, i;
    1194                 :             : 
    1195                 :     3814687 :       a = node->regno_allocno_map[regno];
    1196                 :     3814687 :       if ((to = ALLOCNO_EMIT_DATA (a)->mem_optimized_dest) != NULL)
    1197                 :        5778 :         a = to;
    1198                 :     3814687 :       nr = ALLOCNO_NUM_OBJECTS (a);
    1199                 :     7715785 :       for (i = 0; i < nr; i++)
    1200                 :             :         {
    1201                 :     3901098 :           ira_object_t obj = ALLOCNO_OBJECT (a, i);
    1202                 :     3901098 :           ira_add_live_range_to_object (obj, start, ira_max_point - 1);
    1203                 :             :         }
    1204                 :     3814687 :       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1205                 :           0 :         fprintf
    1206                 :           0 :           (ira_dump_file,
    1207                 :             :            "    Adding range [%d..%d] to live through %s allocno a%dr%d\n",
    1208                 :             :            start, ira_max_point - 1,
    1209                 :             :            to != NULL ? "upper level" : "",
    1210                 :           0 :            ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
    1211                 :             :     }
    1212                 :             : }
    1213                 :             : 
    1214                 :             : /* Process all move list to add ranges, conflicts, copies, and modify
    1215                 :             :    costs for allocnos involved in the moves.  */
    1216                 :             : static void
    1217                 :       34829 : add_ranges_and_copies (void)
    1218                 :             : {
    1219                 :       34829 :   basic_block bb;
    1220                 :       34829 :   edge_iterator ei;
    1221                 :       34829 :   edge e;
    1222                 :       34829 :   ira_loop_tree_node_t node;
    1223                 :       34829 :   bitmap live_through;
    1224                 :             : 
    1225                 :       34829 :   live_through = ira_allocate_bitmap ();
    1226                 :     2645374 :   FOR_EACH_BB_FN (bb, cfun)
    1227                 :             :     {
    1228                 :             :       /* It does not matter what loop_tree_node (of source or
    1229                 :             :          destination block) to use for searching allocnos by their
    1230                 :             :          regnos because of subsequent IR flattening.  */
    1231                 :     2610545 :       node = IRA_BB_NODE (bb)->parent;
    1232                 :     2610545 :       bitmap_copy (live_through, df_get_live_in (bb));
    1233                 :     2610545 :       add_range_and_copies_from_move_list
    1234                 :     2610545 :         (at_bb_start[bb->index], node, live_through, REG_FREQ_FROM_BB (bb));
    1235                 :     2610545 :       bitmap_copy (live_through, df_get_live_out (bb));
    1236                 :     2610545 :       add_range_and_copies_from_move_list
    1237                 :     2610545 :         (at_bb_end[bb->index], node, live_through, REG_FREQ_FROM_BB (bb));
    1238                 :     6579075 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1239                 :             :         {
    1240                 :     3968530 :           bitmap_and (live_through,
    1241                 :     3968530 :                       df_get_live_in (e->dest), df_get_live_out (bb));
    1242                 :     3968530 :           add_range_and_copies_from_move_list
    1243                 :     7935050 :             ((move_t) e->aux, node, live_through,
    1244                 :    11903580 :              REG_FREQ_FROM_EDGE_FREQ (EDGE_FREQUENCY (e)));
    1245                 :             :         }
    1246                 :             :     }
    1247                 :       34829 :   ira_free_bitmap (live_through);
    1248                 :       34829 : }
    1249                 :             : 
    1250                 :             : /* The entry function changes code and generates shuffling allocnos on
    1251                 :             :    region borders for the regional (LOOPS_P is TRUE in this case)
    1252                 :             :    register allocation.  */
    1253                 :             : void
    1254                 :     1419736 : ira_emit (bool loops_p)
    1255                 :             : {
    1256                 :     1419736 :   basic_block bb;
    1257                 :     1419736 :   rtx_insn *insn;
    1258                 :     1419736 :   edge_iterator ei;
    1259                 :     1419736 :   edge e;
    1260                 :     1419736 :   ira_allocno_t a;
    1261                 :     1419736 :   ira_allocno_iterator ai;
    1262                 :     1419736 :   size_t sz;
    1263                 :             : 
    1264                 :    37334162 :   FOR_EACH_ALLOCNO (a, ai)
    1265                 :    35914426 :     ALLOCNO_EMIT_DATA (a)->reg = regno_reg_rtx[ALLOCNO_REGNO (a)];
    1266                 :     1419736 :   if (! loops_p)
    1267                 :     1384907 :     return;
    1268                 :       34829 :   sz = sizeof (move_t) * last_basic_block_for_fn (cfun);
    1269                 :       34829 :   at_bb_start = (move_t *) ira_allocate (sz);
    1270                 :       34829 :   memset (at_bb_start, 0, sz);
    1271                 :       34829 :   at_bb_end = (move_t *) ira_allocate (sz);
    1272                 :       34829 :   memset (at_bb_end, 0, sz);
    1273                 :       34829 :   local_allocno_bitmap = ira_allocate_bitmap ();
    1274                 :       34829 :   used_regno_bitmap = ira_allocate_bitmap ();
    1275                 :       34829 :   renamed_regno_bitmap = ira_allocate_bitmap ();
    1276                 :       34829 :   max_regno_before_changing = max_reg_num ();
    1277                 :       34829 :   ira_traverse_loop_tree (true, ira_loop_tree_root, change_loop, NULL);
    1278                 :       34829 :   set_allocno_somewhere_renamed_p ();
    1279                 :       34829 :   ira_free_bitmap (used_regno_bitmap);
    1280                 :       34829 :   ira_free_bitmap (renamed_regno_bitmap);
    1281                 :       34829 :   ira_free_bitmap (local_allocno_bitmap);
    1282                 :       34829 :   setup_entered_from_non_parent_p ();
    1283                 :     2645374 :   FOR_EACH_BB_FN (bb, cfun)
    1284                 :             :     {
    1285                 :     2610545 :       at_bb_start[bb->index] = NULL;
    1286                 :     2610545 :       at_bb_end[bb->index] = NULL;
    1287                 :     6579075 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1288                 :     3968530 :         if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
    1289                 :     3931350 :           generate_edge_moves (e);
    1290                 :             :     }
    1291                 :       34829 :   allocno_last_set
    1292                 :       34829 :     = (move_t *) ira_allocate (sizeof (move_t) * max_reg_num ());
    1293                 :       34829 :   allocno_last_set_check
    1294                 :       34829 :     = (int *) ira_allocate (sizeof (int) * max_reg_num ());
    1295                 :       34829 :   memset (allocno_last_set_check, 0, sizeof (int) * max_reg_num ());
    1296                 :       34829 :   memset (hard_regno_last_set_check, 0, sizeof (hard_regno_last_set_check));
    1297                 :       34829 :   curr_tick = 0;
    1298                 :     2645374 :   FOR_EACH_BB_FN (bb, cfun)
    1299                 :     2610545 :     unify_moves (bb, true);
    1300                 :     2645374 :   FOR_EACH_BB_FN (bb, cfun)
    1301                 :     2610545 :     unify_moves (bb, false);
    1302                 :       34829 :   move_vec.create (ira_allocnos_num);
    1303                 :       34829 :   emit_moves ();
    1304                 :       34829 :   add_ranges_and_copies ();
    1305                 :             :   /* Clean up: */
    1306                 :     2645374 :   FOR_EACH_BB_FN (bb, cfun)
    1307                 :             :     {
    1308                 :     2610545 :       free_move_list (at_bb_start[bb->index]);
    1309                 :     2610545 :       free_move_list (at_bb_end[bb->index]);
    1310                 :     6579075 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1311                 :             :         {
    1312                 :     3968530 :           free_move_list ((move_t) e->aux);
    1313                 :     3968530 :           e->aux = NULL;
    1314                 :             :         }
    1315                 :             :     }
    1316                 :       34829 :   move_vec.release ();
    1317                 :       34829 :   ira_free (allocno_last_set_check);
    1318                 :       34829 :   ira_free (allocno_last_set);
    1319                 :       34829 :   commit_edge_insertions ();
    1320                 :             :   /* Fix insn codes.  It is necessary to do it before reload because
    1321                 :             :      reload assumes initial insn codes defined.  The insn codes can be
    1322                 :             :      invalidated by CFG infrastructure for example in jump
    1323                 :             :      redirection.  */
    1324                 :     2734085 :   FOR_EACH_BB_FN (bb, cfun)
    1325                 :    33594324 :     FOR_BB_INSNS_REVERSE (bb, insn)
    1326                 :    30895068 :       if (INSN_P (insn))
    1327                 :    25948593 :         recog_memoized (insn);
    1328                 :       34829 :   ira_free (at_bb_end);
    1329                 :       34829 :   ira_free (at_bb_start);
    1330                 :             : }
        

Generated by: LCOV version 2.0-1

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.