LCOV - code coverage report
Current view: top level - gcc - lcm.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 308 308
Test Date: 2024-12-21 13:15:12 Functions: 100.0 % 11 11
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Generic partial redundancy elimination with lazy code motion support.
       2                 :             :    Copyright (C) 1998-2024 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : /* These routines are meant to be used by various optimization
      21                 :             :    passes which can be modeled as lazy code motion problems.
      22                 :             :    Including, but not limited to:
      23                 :             : 
      24                 :             :         * Traditional partial redundancy elimination.
      25                 :             : 
      26                 :             :         * Placement of caller/caller register save/restores.
      27                 :             : 
      28                 :             :         * Load/store motion.
      29                 :             : 
      30                 :             :         * Copy motion.
      31                 :             : 
      32                 :             :         * Conversion of flat register files to a stacked register
      33                 :             :         model.
      34                 :             : 
      35                 :             :         * Dead load/store elimination.
      36                 :             : 
      37                 :             :   These routines accept as input:
      38                 :             : 
      39                 :             :         * Basic block information (number of blocks, lists of
      40                 :             :         predecessors and successors).  Note the granularity
      41                 :             :         does not need to be basic block, they could be statements
      42                 :             :         or functions.
      43                 :             : 
      44                 :             :         * Bitmaps of local properties (computed, transparent and
      45                 :             :         anticipatable expressions).
      46                 :             : 
      47                 :             :   The output of these routines is bitmap of redundant computations
      48                 :             :   and a bitmap of optimal placement points.  */
      49                 :             : 
      50                 :             : 
      51                 :             : #include "config.h"
      52                 :             : #include "system.h"
      53                 :             : #include "coretypes.h"
      54                 :             : #include "backend.h"
      55                 :             : #include "cfganal.h"
      56                 :             : #include "lcm.h"
      57                 :             : 
      58                 :             : /* Edge based LCM routines.  */
      59                 :             : static void compute_laterin (struct edge_list *, sbitmap *, sbitmap *,
      60                 :             :                              sbitmap *, sbitmap *);
      61                 :             : static void compute_insert_delete (struct edge_list *edge_list, sbitmap *,
      62                 :             :                                    sbitmap *, sbitmap *, sbitmap *, sbitmap *);
      63                 :             : 
      64                 :             : /* Edge based LCM routines on a reverse flowgraph.  */
      65                 :             : static void compute_farthest (struct edge_list *, int, sbitmap *, sbitmap *,
      66                 :             :                               sbitmap*, sbitmap *, sbitmap *);
      67                 :             : static void compute_nearerout (struct edge_list *, sbitmap *, sbitmap *,
      68                 :             :                                sbitmap *, sbitmap *);
      69                 :             : static void compute_rev_insert_delete (struct edge_list *edge_list, sbitmap *,
      70                 :             :                                        sbitmap *, sbitmap *, sbitmap *,
      71                 :             :                                        sbitmap *);
      72                 :             : 
      73                 :             : /* Edge based lcm routines.  */
      74                 :             : 
      75                 :             : /* Compute expression anticipatability at entrance and exit of each block.
      76                 :             :    This is done based on the flow graph, and not on the pred-succ lists.
      77                 :             :    Other than that, its pretty much identical to compute_antinout.  */
      78                 :             : 
      79                 :             : void
      80                 :      473335 : compute_antinout_edge (sbitmap *antloc, sbitmap *transp, sbitmap *antin,
      81                 :             :                        sbitmap *antout)
      82                 :             : {
      83                 :      473335 :   basic_block bb;
      84                 :      473335 :   edge e;
      85                 :      473335 :   basic_block *worklist, *qin, *qout, *qend;
      86                 :      473335 :   unsigned int qlen;
      87                 :      473335 :   edge_iterator ei;
      88                 :             : 
      89                 :             :   /* Allocate a worklist array/queue.  Entries are only added to the
      90                 :             :      list if they were not already on the list.  So the size is
      91                 :             :      bounded by the number of basic blocks.  */
      92                 :      473335 :   qin = qout = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
      93                 :             : 
      94                 :             :   /* We want a maximal solution, so make an optimistic initialization of
      95                 :             :      ANTIN.  */
      96                 :      473335 :   bitmap_vector_ones (antin, last_basic_block_for_fn (cfun));
      97                 :             : 
      98                 :             :   /* Put every block on the worklist; this is necessary because of the
      99                 :             :      optimistic initialization of ANTIN above.  Use reverse postorder
     100                 :             :      on the inverted graph to make the backward dataflow problem require
     101                 :             :      less iterations.  */
     102                 :      473335 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
     103                 :      473335 :   int n = inverted_rev_post_order_compute (cfun, rpo);
     104                 :    10383691 :   for (int i = 0; i < n; ++i)
     105                 :             :     {
     106                 :     9910356 :       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
     107                 :     9910356 :       if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
     108                 :     9437021 :           || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     109                 :      946670 :         continue;
     110                 :     8963686 :       *qin++ = bb;
     111                 :     8963686 :       bb->aux = bb;
     112                 :             :     }
     113                 :      473335 :   free (rpo);
     114                 :             : 
     115                 :      473335 :   qin = worklist;
     116                 :      473335 :   qend = &worklist[n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS];
     117                 :      473335 :   qlen = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
     118                 :             : 
     119                 :             :   /* Mark blocks which are predecessors of the exit block so that we
     120                 :             :      can easily identify them below.  */
     121                 :     1353177 :   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
     122                 :      879842 :     e->src->aux = EXIT_BLOCK_PTR_FOR_FN (cfun);
     123                 :             : 
     124                 :             :   /* Iterate until the worklist is empty.  */
     125                 :    10341112 :   while (qlen)
     126                 :             :     {
     127                 :             :       /* Take the first entry off the worklist.  */
     128                 :     9867777 :       bb = *qout++;
     129                 :     9867777 :       qlen--;
     130                 :             : 
     131                 :     9867777 :       if (qout >= qend)
     132                 :      473911 :         qout = worklist;
     133                 :             : 
     134                 :     9867777 :       if (bb->aux == EXIT_BLOCK_PTR_FOR_FN (cfun))
     135                 :             :         /* Do not clear the aux field for blocks which are predecessors of
     136                 :             :            the EXIT block.  That way we never add then to the worklist
     137                 :             :            again.  */
     138                 :      879842 :         bitmap_clear (antout[bb->index]);
     139                 :             :       else
     140                 :             :         {
     141                 :             :           /* Clear the aux field of this block so that it can be added to
     142                 :             :              the worklist again if necessary.  */
     143                 :     8987935 :           bb->aux = NULL;
     144                 :     8987935 :           bitmap_intersection_of_succs (antout[bb->index], antin, bb);
     145                 :             :         }
     146                 :             : 
     147                 :     9867777 :       if (bitmap_or_and (antin[bb->index], antloc[bb->index],
     148                 :     9867777 :                                    transp[bb->index], antout[bb->index]))
     149                 :             :         /* If the in state of this block changed, then we need
     150                 :             :            to add the predecessors of this block to the worklist
     151                 :             :            if they are not already on the worklist.  */
     152                 :    22691632 :         FOR_EACH_EDGE (e, ei, bb->preds)
     153                 :    13525481 :           if (!e->src->aux && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
     154                 :             :             {
     155                 :      904091 :               *qin++ = e->src;
     156                 :      904091 :               e->src->aux = e;
     157                 :      904091 :               qlen++;
     158                 :      904091 :               if (qin >= qend)
     159                 :         576 :                 qin = worklist;
     160                 :             :             }
     161                 :             :     }
     162                 :             : 
     163                 :      473335 :   clear_aux_for_edges ();
     164                 :      473335 :   clear_aux_for_blocks ();
     165                 :      473335 :   free (worklist);
     166                 :      473335 : }
     167                 :             : 
     168                 :             : /* Compute the earliest vector for edge based lcm.  */
     169                 :             : 
     170                 :             : void
     171                 :      473303 : compute_earliest (struct edge_list *edge_list, int n_exprs, sbitmap *antin,
     172                 :             :                   sbitmap *antout, sbitmap *avout, sbitmap *kill,
     173                 :             :                   sbitmap *earliest)
     174                 :             : {
     175                 :      473303 :   int x, num_edges;
     176                 :      473303 :   basic_block pred, succ;
     177                 :             : 
     178                 :      473303 :   num_edges = NUM_EDGES (edge_list);
     179                 :             : 
     180                 :      473303 :   auto_sbitmap difference (n_exprs), temp_bitmap (n_exprs);
     181                 :    15055978 :   for (x = 0; x < num_edges; x++)
     182                 :             :     {
     183                 :    14109372 :       pred = INDEX_EDGE_PRED_BB (edge_list, x);
     184                 :    14109372 :       succ = INDEX_EDGE_SUCC_BB (edge_list, x);
     185                 :    14109372 :       if (pred == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     186                 :      473303 :         bitmap_copy (earliest[x], antin[succ->index]);
     187                 :             :       else
     188                 :             :         {
     189                 :    13636069 :           if (succ == EXIT_BLOCK_PTR_FOR_FN (cfun))
     190                 :      879809 :             bitmap_clear (earliest[x]);
     191                 :             :           else
     192                 :             :             {
     193                 :    12756260 :               bitmap_and_compl (difference, antin[succ->index],
     194                 :    12756260 :                                   avout[pred->index]);
     195                 :    12756260 :               bitmap_not (temp_bitmap, antout[pred->index]);
     196                 :    12756260 :               bitmap_and_or (earliest[x], difference,
     197                 :    12756260 :                                     kill[pred->index], temp_bitmap);
     198                 :             :             }
     199                 :             :         }
     200                 :             :     }
     201                 :      473303 : }
     202                 :             : 
     203                 :             : /* later(p,s) is dependent on the calculation of laterin(p).
     204                 :             :    laterin(p) is dependent on the calculation of later(p2,p).
     205                 :             : 
     206                 :             :      laterin(ENTRY) is defined as all 0's
     207                 :             :      later(ENTRY, succs(ENTRY)) are defined using laterin(ENTRY)
     208                 :             :      laterin(succs(ENTRY)) is defined by later(ENTRY, succs(ENTRY)).
     209                 :             : 
     210                 :             :    If we progress in this manner, starting with all basic blocks
     211                 :             :    in the work list, anytime we change later(bb), we need to add
     212                 :             :    succs(bb) to the worklist if they are not already on the worklist.
     213                 :             : 
     214                 :             :    Boundary conditions:
     215                 :             : 
     216                 :             :      We prime the worklist all the normal basic blocks.   The ENTRY block can
     217                 :             :      never be added to the worklist since it is never the successor of any
     218                 :             :      block.  We explicitly prevent the EXIT block from being added to the
     219                 :             :      worklist.
     220                 :             : 
     221                 :             :      We optimistically initialize LATER.  That is the only time this routine
     222                 :             :      will compute LATER for an edge out of the entry block since the entry
     223                 :             :      block is never on the worklist.  Thus, LATERIN is neither used nor
     224                 :             :      computed for the ENTRY block.
     225                 :             : 
     226                 :             :      Since the EXIT block is never added to the worklist, we will neither
     227                 :             :      use nor compute LATERIN for the exit block.  Edges which reach the
     228                 :             :      EXIT block are handled in the normal fashion inside the loop.  However,
     229                 :             :      the insertion/deletion computation needs LATERIN(EXIT), so we have
     230                 :             :      to compute it.  */
     231                 :             : 
     232                 :             : static void
     233                 :      473303 : compute_laterin (struct edge_list *edge_list, sbitmap *earliest,
     234                 :             :                  sbitmap *antloc, sbitmap *later, sbitmap *laterin)
     235                 :             : {
     236                 :      473303 :   int num_edges, i;
     237                 :      473303 :   edge e;
     238                 :      473303 :   basic_block *worklist, *qin, *qout, *qend, bb;
     239                 :      473303 :   unsigned int qlen;
     240                 :      473303 :   edge_iterator ei;
     241                 :             : 
     242                 :      473303 :   num_edges = NUM_EDGES (edge_list);
     243                 :             : 
     244                 :             :   /* Allocate a worklist array/queue.  Entries are only added to the
     245                 :             :      list if they were not already on the list.  So the size is
     246                 :             :      bounded by the number of basic blocks.  */
     247                 :      473303 :   qin = qout = worklist
     248                 :      473303 :     = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
     249                 :             : 
     250                 :             :   /* Initialize a mapping from each edge to its index.  */
     251                 :    15055978 :   for (i = 0; i < num_edges; i++)
     252                 :    14109372 :     INDEX_EDGE (edge_list, i)->aux = (void *) (size_t) i;
     253                 :             : 
     254                 :             :   /* We want a maximal solution, so initially consider LATER true for
     255                 :             :      all edges.  This allows propagation through a loop since the incoming
     256                 :             :      loop edge will have LATER set, so if all the other incoming edges
     257                 :             :      to the loop are set, then LATERIN will be set for the head of the
     258                 :             :      loop.
     259                 :             : 
     260                 :             :      If the optimistic setting of LATER on that edge was incorrect (for
     261                 :             :      example the expression is ANTLOC in a block within the loop) then
     262                 :             :      this algorithm will detect it when we process the block at the head
     263                 :             :      of the optimistic edge.  That will requeue the affected blocks.  */
     264                 :      473303 :   bitmap_vector_ones (later, num_edges);
     265                 :             : 
     266                 :             :   /* Note that even though we want an optimistic setting of LATER, we
     267                 :             :      do not want to be overly optimistic.  Consider an outgoing edge from
     268                 :             :      the entry block.  That edge should always have a LATER value the
     269                 :             :      same as EARLIEST for that edge.  */
     270                 :      946606 :   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     271                 :      473303 :     bitmap_copy (later[(size_t) e->aux], earliest[(size_t) e->aux]);
     272                 :             : 
     273                 :             :   /* Add all the blocks to the worklist.  This prevents an early exit from
     274                 :             :      the loop given our optimistic initialization of LATER above.  */
     275                 :      473303 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
     276                 :      473303 :   int n = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, false);
     277                 :     9436850 :   for (int i = 0; i < n; ++i)
     278                 :             :     {
     279                 :     8963547 :       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
     280                 :     8963547 :       *qin++ = bb;
     281                 :     8963547 :       bb->aux = bb;
     282                 :             :     }
     283                 :      473303 :   free (rpo);
     284                 :             : 
     285                 :             :   /* Note that we do not use the last allocated element for our queue,
     286                 :             :      as EXIT_BLOCK is never inserted into it. */
     287                 :      473303 :   qin = worklist;
     288                 :      473303 :   qend = &worklist[n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS];
     289                 :      473303 :   qlen = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
     290                 :             : 
     291                 :             :   /* Iterate until the worklist is empty.  */
     292                 :    10135651 :   while (qlen)
     293                 :             :     {
     294                 :             :       /* Take the first entry off the worklist.  */
     295                 :     9662348 :       bb = *qout++;
     296                 :     9662348 :       bb->aux = NULL;
     297                 :     9662348 :       qlen--;
     298                 :     9662348 :       if (qout >= qend)
     299                 :      473788 :         qout = worklist;
     300                 :             : 
     301                 :             :       /* Compute LATERIN as the intersection of LATER for each incoming
     302                 :             :          edge to BB.  */
     303                 :     9662348 :       bitmap_ones (laterin[bb->index]);
     304                 :    24436799 :       FOR_EACH_EDGE (e, ei, bb->preds)
     305                 :    14774451 :         bitmap_and (laterin[bb->index], laterin[bb->index],
     306                 :    14774451 :                     later[(size_t)e->aux]);
     307                 :             : 
     308                 :             :       /* Calculate LATER for all outgoing edges of BB.  */
     309                 :    24586276 :       FOR_EACH_EDGE (e, ei, bb->succs)
     310                 :    14923928 :         if (bitmap_ior_and_compl (later[(size_t) e->aux],
     311                 :    14923928 :                                   earliest[(size_t) e->aux],
     312                 :    14923928 :                                   laterin[bb->index],
     313                 :    14923928 :                                   antloc[bb->index])
     314                 :             :             /* If LATER for an outgoing edge was changed, then we need
     315                 :             :                to add the target of the outgoing edge to the worklist.  */
     316                 :    14923928 :             && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun) && e->dest->aux == 0)
     317                 :             :           {
     318                 :      698801 :             *qin++ = e->dest;
     319                 :      698801 :             e->dest->aux = e;
     320                 :      698801 :             qlen++;
     321                 :      698801 :             if (qin >= qend)
     322                 :         485 :               qin = worklist;
     323                 :             :           }
     324                 :             :     }
     325                 :             : 
     326                 :             :   /* Computation of insertion and deletion points requires computing LATERIN
     327                 :             :      for the EXIT block.  We allocated an extra entry in the LATERIN array
     328                 :             :      for just this purpose.  */
     329                 :      473303 :   bitmap_ones (laterin[last_basic_block_for_fn (cfun)]);
     330                 :     1353112 :   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
     331                 :      879809 :     bitmap_and (laterin[last_basic_block_for_fn (cfun)],
     332                 :      879809 :                 laterin[last_basic_block_for_fn (cfun)],
     333                 :      879809 :                 later[(size_t) e->aux]);
     334                 :             : 
     335                 :      473303 :   clear_aux_for_edges ();
     336                 :      473303 :   free (worklist);
     337                 :      473303 : }
     338                 :             : 
     339                 :             : /* Compute the insertion and deletion points for edge based LCM.  */
     340                 :             : 
     341                 :             : static void
     342                 :      473303 : compute_insert_delete (struct edge_list *edge_list, sbitmap *antloc,
     343                 :             :                        sbitmap *later, sbitmap *laterin, sbitmap *insert,
     344                 :             :                        sbitmap *del)
     345                 :             : {
     346                 :      473303 :   int x;
     347                 :      473303 :   basic_block bb;
     348                 :             : 
     349                 :     9436850 :   FOR_EACH_BB_FN (bb, cfun)
     350                 :     8963547 :     bitmap_and_compl (del[bb->index], antloc[bb->index],
     351                 :     8963547 :                         laterin[bb->index]);
     352                 :             : 
     353                 :    14582675 :   for (x = 0; x < NUM_EDGES (edge_list); x++)
     354                 :             :     {
     355                 :    14109372 :       basic_block b = INDEX_EDGE_SUCC_BB (edge_list, x);
     356                 :             : 
     357                 :    14109372 :       if (b == EXIT_BLOCK_PTR_FOR_FN (cfun))
     358                 :      879809 :         bitmap_and_compl (insert[x], later[x],
     359                 :      879809 :                           laterin[last_basic_block_for_fn (cfun)]);
     360                 :             :       else
     361                 :    13229563 :         bitmap_and_compl (insert[x], later[x], laterin[b->index]);
     362                 :             :     }
     363                 :      473303 : }
     364                 :             : 
     365                 :             : /* Given local properties TRANSP, ANTLOC, AVLOC, KILL return the insert and
     366                 :             :    delete vectors for edge based LCM  and return the AVIN, AVOUT bitmap.
     367                 :             :    map the insert vector to what edge an expression should be inserted on.  */
     368                 :             : 
     369                 :             : struct edge_list *
     370                 :      473303 : pre_edge_lcm_avs (int n_exprs, sbitmap *transp,
     371                 :             :               sbitmap *avloc, sbitmap *antloc, sbitmap *kill,
     372                 :             :               sbitmap *avin, sbitmap *avout,
     373                 :             :               sbitmap **insert, sbitmap **del)
     374                 :             : {
     375                 :      473303 :   sbitmap *antin, *antout, *earliest;
     376                 :      473303 :   sbitmap *later, *laterin;
     377                 :      473303 :   struct edge_list *edge_list;
     378                 :      473303 :   int num_edges;
     379                 :             : 
     380                 :      473303 :   edge_list = create_edge_list ();
     381                 :      473303 :   num_edges = NUM_EDGES (edge_list);
     382                 :             : 
     383                 :             : #ifdef LCM_DEBUG_INFO
     384                 :             :   if (dump_file)
     385                 :             :     {
     386                 :             :       fprintf (dump_file, "Edge List:\n");
     387                 :             :       verify_edge_list (dump_file, edge_list);
     388                 :             :       print_edge_list (dump_file, edge_list);
     389                 :             :       dump_bitmap_vector (dump_file, "transp", "", transp,
     390                 :             :                           last_basic_block_for_fn (cfun));
     391                 :             :       dump_bitmap_vector (dump_file, "antloc", "", antloc,
     392                 :             :                           last_basic_block_for_fn (cfun));
     393                 :             :       dump_bitmap_vector (dump_file, "avloc", "", avloc,
     394                 :             :                           last_basic_block_for_fn (cfun));
     395                 :             :       dump_bitmap_vector (dump_file, "kill", "", kill,
     396                 :             :                           last_basic_block_for_fn (cfun));
     397                 :             :     }
     398                 :             : #endif
     399                 :             : 
     400                 :             :   /* Compute global availability.  */
     401                 :      473303 :   compute_available (avloc, kill, avout, avin);
     402                 :             : 
     403                 :             :   /* Compute global anticipatability.  */
     404                 :      473303 :   antin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     405                 :      473303 :   antout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     406                 :      473303 :   compute_antinout_edge (antloc, transp, antin, antout);
     407                 :             : 
     408                 :             : #ifdef LCM_DEBUG_INFO
     409                 :             :   if (dump_file)
     410                 :             :     {
     411                 :             :       dump_bitmap_vector (dump_file, "antin", "", antin,
     412                 :             :                           last_basic_block_for_fn (cfun));
     413                 :             :       dump_bitmap_vector (dump_file, "antout", "", antout,
     414                 :             :                           last_basic_block_for_fn (cfun));
     415                 :             :     }
     416                 :             : #endif
     417                 :             : 
     418                 :             :   /* Compute earliestness.  */
     419                 :      473303 :   earliest = sbitmap_vector_alloc (num_edges, n_exprs);
     420                 :      473303 :   compute_earliest (edge_list, n_exprs, antin, antout, avout, kill, earliest);
     421                 :             : 
     422                 :             : #ifdef LCM_DEBUG_INFO
     423                 :             :   if (dump_file)
     424                 :             :     dump_bitmap_vector (dump_file, "earliest", "", earliest, num_edges);
     425                 :             : #endif
     426                 :             : 
     427                 :      473303 :   sbitmap_vector_free (antout);
     428                 :      473303 :   sbitmap_vector_free (antin);
     429                 :             : 
     430                 :      473303 :   later = sbitmap_vector_alloc (num_edges, n_exprs);
     431                 :             : 
     432                 :             :   /* Allocate an extra element for the exit block in the laterin vector.  */
     433                 :      473303 :   laterin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun) + 1,
     434                 :             :                                   n_exprs);
     435                 :      473303 :   compute_laterin (edge_list, earliest, antloc, later, laterin);
     436                 :             : 
     437                 :             : #ifdef LCM_DEBUG_INFO
     438                 :             :   if (dump_file)
     439                 :             :     {
     440                 :             :       dump_bitmap_vector (dump_file, "laterin", "", laterin,
     441                 :             :                           last_basic_block_for_fn (cfun) + 1);
     442                 :             :       dump_bitmap_vector (dump_file, "later", "", later, num_edges);
     443                 :             :     }
     444                 :             : #endif
     445                 :             : 
     446                 :      473303 :   sbitmap_vector_free (earliest);
     447                 :             : 
     448                 :      473303 :   *insert = sbitmap_vector_alloc (num_edges, n_exprs);
     449                 :      473303 :   *del = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     450                 :      473303 :   bitmap_vector_clear (*insert, num_edges);
     451                 :      473303 :   bitmap_vector_clear (*del, last_basic_block_for_fn (cfun));
     452                 :      473303 :   compute_insert_delete (edge_list, antloc, later, laterin, *insert, *del);
     453                 :             : 
     454                 :      473303 :   sbitmap_vector_free (laterin);
     455                 :      473303 :   sbitmap_vector_free (later);
     456                 :             : 
     457                 :             : #ifdef LCM_DEBUG_INFO
     458                 :             :   if (dump_file)
     459                 :             :     {
     460                 :             :       dump_bitmap_vector (dump_file, "pre_insert_map", "", *insert, num_edges);
     461                 :             :       dump_bitmap_vector (dump_file, "pre_delete_map", "", *del,
     462                 :             :                           last_basic_block_for_fn (cfun));
     463                 :             :     }
     464                 :             : #endif
     465                 :             : 
     466                 :      473303 :   return edge_list;
     467                 :             : }
     468                 :             : 
     469                 :             : /* Wrapper to allocate avin/avout and call pre_edge_lcm_avs.  */
     470                 :             : 
     471                 :             : struct edge_list *
     472                 :      397397 : pre_edge_lcm (int n_exprs, sbitmap *transp,
     473                 :             :               sbitmap *avloc, sbitmap *antloc, sbitmap *kill,
     474                 :             :               sbitmap **insert, sbitmap **del)
     475                 :             : {
     476                 :      397397 :   struct edge_list *edge_list;
     477                 :      397397 :   sbitmap *avin, *avout;
     478                 :             : 
     479                 :      397397 :   avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     480                 :      397397 :   avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     481                 :             : 
     482                 :      397397 :   edge_list = pre_edge_lcm_avs (n_exprs, transp, avloc, antloc, kill,
     483                 :             :                                  avin, avout, insert, del);
     484                 :             : 
     485                 :      397397 :   sbitmap_vector_free (avout);
     486                 :      397397 :   sbitmap_vector_free (avin);
     487                 :             : 
     488                 :      397397 :   return edge_list;
     489                 :             : }
     490                 :             : 
     491                 :             : /* Compute the AVIN and AVOUT vectors from the AVLOC and KILL vectors.
     492                 :             :    Return the number of passes we performed to iterate to a solution.  */
     493                 :             : 
     494                 :             : void
     495                 :     1778088 : compute_available (sbitmap *avloc, sbitmap *kill, sbitmap *avout,
     496                 :             :                    sbitmap *avin)
     497                 :             : {
     498                 :     1778088 :   edge e;
     499                 :     1778088 :   basic_block *worklist, *qin, *qout, *qend, bb;
     500                 :     1778088 :   unsigned int qlen;
     501                 :     1778088 :   edge_iterator ei;
     502                 :             : 
     503                 :             :   /* Allocate a worklist array/queue.  Entries are only added to the
     504                 :             :      list if they were not already on the list.  So the size is
     505                 :             :      bounded by the number of basic blocks.  */
     506                 :     3556176 :   qin = qout = worklist =
     507                 :     1778088 :     XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
     508                 :             : 
     509                 :             :   /* We want a maximal solution.  */
     510                 :     1778088 :   bitmap_vector_ones (avout, last_basic_block_for_fn (cfun));
     511                 :             : 
     512                 :             :   /* Put every block on the worklist; this is necessary because of the
     513                 :             :      optimistic initialization of AVOUT above.  Use reverse postorder
     514                 :             :      to make the forward dataflow problem require less iterations.  */
     515                 :     1778088 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
     516                 :     1778088 :   int n = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, false);
     517                 :    39225763 :   for (int i = 0; i < n; ++i)
     518                 :             :     {
     519                 :    37447675 :       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
     520                 :    37447675 :       *qin++ = bb;
     521                 :    37447675 :       bb->aux = bb;
     522                 :             :     }
     523                 :     1778088 :   free (rpo);
     524                 :             : 
     525                 :     1778088 :   qin = worklist;
     526                 :     1778088 :   qend = &worklist[n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS];
     527                 :     1778088 :   qlen = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
     528                 :             : 
     529                 :             :   /* Mark blocks which are successors of the entry block so that we
     530                 :             :      can easily identify them below.  */
     531                 :     3556176 :   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     532                 :     1778088 :     e->dest->aux = ENTRY_BLOCK_PTR_FOR_FN (cfun);
     533                 :             : 
     534                 :             :   /* Iterate until the worklist is empty.  */
     535                 :    55629033 :   while (qlen)
     536                 :             :     {
     537                 :             :       /* Take the first entry off the worklist.  */
     538                 :    53850945 :       bb = *qout++;
     539                 :    53850945 :       qlen--;
     540                 :             : 
     541                 :    53850945 :       if (qout >= qend)
     542                 :     1888222 :         qout = worklist;
     543                 :             : 
     544                 :             :       /* If one of the predecessor blocks is the ENTRY block, then the
     545                 :             :          intersection of avouts is the null set.  We can identify such blocks
     546                 :             :          by the special value in the AUX field in the block structure.  */
     547                 :    53850945 :       if (bb->aux == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     548                 :             :         /* Do not clear the aux field for blocks which are successors of the
     549                 :             :            ENTRY block.  That way we never add then to the worklist again.  */
     550                 :     1778088 :         bitmap_clear (avin[bb->index]);
     551                 :             :       else
     552                 :             :         {
     553                 :             :           /* Clear the aux field of this block so that it can be added to
     554                 :             :              the worklist again if necessary.  */
     555                 :    52072857 :           bb->aux = NULL;
     556                 :    52072857 :           bitmap_intersection_of_preds (avin[bb->index], avout, bb);
     557                 :             :         }
     558                 :             : 
     559                 :    53850945 :       if (bitmap_ior_and_compl (avout[bb->index], avloc[bb->index],
     560                 :    53850945 :                                     avin[bb->index], kill[bb->index]))
     561                 :             :         /* If the out state of this block changed, then we need
     562                 :             :            to add the successors of this block to the worklist
     563                 :             :            if they are not already on the worklist.  */
     564                 :   118357247 :         FOR_EACH_EDGE (e, ei, bb->succs)
     565                 :    70830776 :           if (!e->dest->aux && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
     566                 :             :             {
     567                 :    16403270 :               *qin++ = e->dest;
     568                 :    16403270 :               e->dest->aux = e;
     569                 :    16403270 :               qlen++;
     570                 :             : 
     571                 :    16403270 :               if (qin >= qend)
     572                 :      110134 :                 qin = worklist;
     573                 :             :             }
     574                 :             :     }
     575                 :             : 
     576                 :     1778088 :   clear_aux_for_edges ();
     577                 :     1778088 :   clear_aux_for_blocks ();
     578                 :     1778088 :   free (worklist);
     579                 :     1778088 : }
     580                 :             : 
     581                 :             : /* Compute the farthest vector for edge based lcm.  */
     582                 :             : 
     583                 :             : static void
     584                 :          32 : compute_farthest (struct edge_list *edge_list, int n_exprs,
     585                 :             :                   sbitmap *st_avout, sbitmap *st_avin, sbitmap *st_antin,
     586                 :             :                   sbitmap *kill, sbitmap *farthest)
     587                 :             : {
     588                 :          32 :   int x, num_edges;
     589                 :          32 :   basic_block pred, succ;
     590                 :             : 
     591                 :          32 :   num_edges = NUM_EDGES (edge_list);
     592                 :             : 
     593                 :          32 :   auto_sbitmap difference (n_exprs), temp_bitmap (n_exprs);
     594                 :         293 :   for (x = 0; x < num_edges; x++)
     595                 :             :     {
     596                 :         229 :       pred = INDEX_EDGE_PRED_BB (edge_list, x);
     597                 :         229 :       succ = INDEX_EDGE_SUCC_BB (edge_list, x);
     598                 :         229 :       if (succ == EXIT_BLOCK_PTR_FOR_FN (cfun))
     599                 :          33 :         bitmap_copy (farthest[x], st_avout[pred->index]);
     600                 :             :       else
     601                 :             :         {
     602                 :         196 :           if (pred == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     603                 :          32 :             bitmap_clear (farthest[x]);
     604                 :             :           else
     605                 :             :             {
     606                 :         164 :               bitmap_and_compl (difference, st_avout[pred->index],
     607                 :         164 :                                   st_antin[succ->index]);
     608                 :         164 :               bitmap_not (temp_bitmap, st_avin[succ->index]);
     609                 :         164 :               bitmap_and_or (farthest[x], difference,
     610                 :         164 :                                     kill[succ->index], temp_bitmap);
     611                 :             :             }
     612                 :             :         }
     613                 :             :     }
     614                 :          32 : }
     615                 :             : 
     616                 :             : /* Compute nearer and nearerout vectors for edge based lcm.
     617                 :             : 
     618                 :             :    This is the mirror of compute_laterin, additional comments on the
     619                 :             :    implementation can be found before compute_laterin.  */
     620                 :             : 
     621                 :             : static void
     622                 :          32 : compute_nearerout (struct edge_list *edge_list, sbitmap *farthest,
     623                 :             :                    sbitmap *st_avloc, sbitmap *nearer, sbitmap *nearerout)
     624                 :             : {
     625                 :          32 :   int num_edges, i;
     626                 :          32 :   edge e;
     627                 :          32 :   basic_block *worklist, *tos, bb;
     628                 :          32 :   edge_iterator ei;
     629                 :             : 
     630                 :          32 :   num_edges = NUM_EDGES (edge_list);
     631                 :             : 
     632                 :             :   /* Allocate a worklist array/queue.  Entries are only added to the
     633                 :             :      list if they were not already on the list.  So the size is
     634                 :             :      bounded by the number of basic blocks.  */
     635                 :          32 :   tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
     636                 :             : 
     637                 :             :   /* Initialize NEARER for each edge and build a mapping from an edge to
     638                 :             :      its index.  */
     639                 :         293 :   for (i = 0; i < num_edges; i++)
     640                 :         229 :     INDEX_EDGE (edge_list, i)->aux = (void *) (size_t) i;
     641                 :             : 
     642                 :             :   /* We want a maximal solution.  */
     643                 :          32 :   bitmap_vector_ones (nearer, num_edges);
     644                 :             : 
     645                 :             :   /* Note that even though we want an optimistic setting of NEARER, we
     646                 :             :      do not want to be overly optimistic.  Consider an incoming edge to
     647                 :             :      the exit block.  That edge should always have a NEARER value the
     648                 :             :      same as FARTHEST for that edge.  */
     649                 :          65 :   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
     650                 :          33 :     bitmap_copy (nearer[(size_t)e->aux], farthest[(size_t)e->aux]);
     651                 :             : 
     652                 :             :   /* Add all the blocks to the worklist.  This prevents an early exit
     653                 :             :      from the loop given our optimistic initialization of NEARER.  */
     654                 :         171 :   FOR_EACH_BB_FN (bb, cfun)
     655                 :             :     {
     656                 :         139 :       *tos++ = bb;
     657                 :         139 :       bb->aux = bb;
     658                 :             :     }
     659                 :             : 
     660                 :             :   /* Iterate until the worklist is empty.  */
     661                 :         192 :   while (tos != worklist)
     662                 :             :     {
     663                 :             :       /* Take the first entry off the worklist.  */
     664                 :         160 :       bb = *--tos;
     665                 :         160 :       bb->aux = NULL;
     666                 :             : 
     667                 :             :       /* Compute the intersection of NEARER for each outgoing edge from B.  */
     668                 :         160 :       bitmap_ones (nearerout[bb->index]);
     669                 :         394 :       FOR_EACH_EDGE (e, ei, bb->succs)
     670                 :         234 :         bitmap_and (nearerout[bb->index], nearerout[bb->index],
     671                 :         234 :                          nearer[(size_t) e->aux]);
     672                 :             : 
     673                 :             :       /* Calculate NEARER for all incoming edges.  */
     674                 :         390 :       FOR_EACH_EDGE (e, ei, bb->preds)
     675                 :         230 :         if (bitmap_ior_and_compl (nearer[(size_t) e->aux],
     676                 :         230 :                                       farthest[(size_t) e->aux],
     677                 :         230 :                                       nearerout[e->dest->index],
     678                 :         230 :                                       st_avloc[e->dest->index])
     679                 :             :             /* If NEARER for an incoming edge was changed, then we need
     680                 :             :                to add the source of the incoming edge to the worklist.  */
     681                 :         230 :             && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun) && e->src->aux == 0)
     682                 :             :           {
     683                 :          21 :             *tos++ = e->src;
     684                 :          21 :             e->src->aux = e;
     685                 :             :           }
     686                 :             :     }
     687                 :             : 
     688                 :             :   /* Computation of insertion and deletion points requires computing NEAREROUT
     689                 :             :      for the ENTRY block.  We allocated an extra entry in the NEAREROUT array
     690                 :             :      for just this purpose.  */
     691                 :          32 :   bitmap_ones (nearerout[last_basic_block_for_fn (cfun)]);
     692                 :          64 :   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     693                 :          32 :     bitmap_and (nearerout[last_basic_block_for_fn (cfun)],
     694                 :          32 :                      nearerout[last_basic_block_for_fn (cfun)],
     695                 :          32 :                      nearer[(size_t) e->aux]);
     696                 :             : 
     697                 :          32 :   clear_aux_for_edges ();
     698                 :          32 :   free (tos);
     699                 :          32 : }
     700                 :             : 
     701                 :             : /* Compute the insertion and deletion points for edge based LCM.  */
     702                 :             : 
     703                 :             : static void
     704                 :          32 : compute_rev_insert_delete (struct edge_list *edge_list, sbitmap *st_avloc,
     705                 :             :                            sbitmap *nearer, sbitmap *nearerout,
     706                 :             :                            sbitmap *insert, sbitmap *del)
     707                 :             : {
     708                 :          32 :   int x;
     709                 :          32 :   basic_block bb;
     710                 :             : 
     711                 :         171 :   FOR_EACH_BB_FN (bb, cfun)
     712                 :         139 :     bitmap_and_compl (del[bb->index], st_avloc[bb->index],
     713                 :         139 :                         nearerout[bb->index]);
     714                 :             : 
     715                 :         261 :   for (x = 0; x < NUM_EDGES (edge_list); x++)
     716                 :             :     {
     717                 :         229 :       basic_block b = INDEX_EDGE_PRED_BB (edge_list, x);
     718                 :         229 :       if (b == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     719                 :          32 :         bitmap_and_compl (insert[x], nearer[x],
     720                 :          32 :                           nearerout[last_basic_block_for_fn (cfun)]);
     721                 :             :       else
     722                 :         197 :         bitmap_and_compl (insert[x], nearer[x], nearerout[b->index]);
     723                 :             :     }
     724                 :          32 : }
     725                 :             : 
     726                 :             : /* Given local properties TRANSP, ST_AVLOC, ST_ANTLOC, KILL return the
     727                 :             :    insert and delete vectors for edge based reverse LCM.  Returns an
     728                 :             :    edgelist which is used to map the insert vector to what edge
     729                 :             :    an expression should be inserted on.  */
     730                 :             : 
     731                 :             : struct edge_list *
     732                 :          32 : pre_edge_rev_lcm (int n_exprs, sbitmap *transp,
     733                 :             :                   sbitmap *st_avloc, sbitmap *st_antloc, sbitmap *kill,
     734                 :             :                   sbitmap **insert, sbitmap **del)
     735                 :             : {
     736                 :          32 :   sbitmap *st_antin, *st_antout;
     737                 :          32 :   sbitmap *st_avout, *st_avin, *farthest;
     738                 :          32 :   sbitmap *nearer, *nearerout;
     739                 :          32 :   struct edge_list *edge_list;
     740                 :          32 :   int num_edges;
     741                 :             : 
     742                 :          32 :   edge_list = create_edge_list ();
     743                 :          32 :   num_edges = NUM_EDGES (edge_list);
     744                 :             : 
     745                 :          32 :   st_antin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     746                 :          32 :   st_antout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     747                 :          32 :   bitmap_vector_clear (st_antin, last_basic_block_for_fn (cfun));
     748                 :          32 :   bitmap_vector_clear (st_antout, last_basic_block_for_fn (cfun));
     749                 :          32 :   compute_antinout_edge (st_antloc, transp, st_antin, st_antout);
     750                 :             : 
     751                 :             :   /* Compute global anticipatability.  */
     752                 :          32 :   st_avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     753                 :          32 :   st_avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     754                 :          32 :   compute_available (st_avloc, kill, st_avout, st_avin);
     755                 :             : 
     756                 :             : #ifdef LCM_DEBUG_INFO
     757                 :             :   if (dump_file)
     758                 :             :     {
     759                 :             :       fprintf (dump_file, "Edge List:\n");
     760                 :             :       verify_edge_list (dump_file, edge_list);
     761                 :             :       print_edge_list (dump_file, edge_list);
     762                 :             :       dump_bitmap_vector (dump_file, "transp", "", transp,
     763                 :             :                           last_basic_block_for_fn (cfun));
     764                 :             :       dump_bitmap_vector (dump_file, "st_avloc", "", st_avloc,
     765                 :             :                           last_basic_block_for_fn (cfun));
     766                 :             :       dump_bitmap_vector (dump_file, "st_antloc", "", st_antloc,
     767                 :             :                           last_basic_block_for_fn (cfun));
     768                 :             :       dump_bitmap_vector (dump_file, "st_antin", "", st_antin,
     769                 :             :                           last_basic_block_for_fn (cfun));
     770                 :             :       dump_bitmap_vector (dump_file, "st_antout", "", st_antout,
     771                 :             :                           last_basic_block_for_fn (cfun));
     772                 :             :       dump_bitmap_vector (dump_file, "st_kill", "", kill,
     773                 :             :                           last_basic_block_for_fn (cfun));
     774                 :             :     }
     775                 :             : #endif
     776                 :             : 
     777                 :             : #ifdef LCM_DEBUG_INFO
     778                 :             :   if (dump_file)
     779                 :             :     {
     780                 :             :       dump_bitmap_vector (dump_file, "st_avout", "", st_avout, last_basic_block_for_fn (cfun));
     781                 :             :       dump_bitmap_vector (dump_file, "st_avin", "", st_avin, last_basic_block_for_fn (cfun));
     782                 :             :     }
     783                 :             : #endif
     784                 :             : 
     785                 :             :   /* Compute farthestness.  */
     786                 :          32 :   farthest = sbitmap_vector_alloc (num_edges, n_exprs);
     787                 :          32 :   compute_farthest (edge_list, n_exprs, st_avout, st_avin, st_antin,
     788                 :             :                     kill, farthest);
     789                 :             : 
     790                 :             : #ifdef LCM_DEBUG_INFO
     791                 :             :   if (dump_file)
     792                 :             :     dump_bitmap_vector (dump_file, "farthest", "", farthest, num_edges);
     793                 :             : #endif
     794                 :             : 
     795                 :          32 :   sbitmap_vector_free (st_antin);
     796                 :          32 :   sbitmap_vector_free (st_antout);
     797                 :             : 
     798                 :          32 :   sbitmap_vector_free (st_avin);
     799                 :          32 :   sbitmap_vector_free (st_avout);
     800                 :             : 
     801                 :          32 :   nearer = sbitmap_vector_alloc (num_edges, n_exprs);
     802                 :             : 
     803                 :             :   /* Allocate an extra element for the entry block.  */
     804                 :          32 :   nearerout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun) + 1,
     805                 :             :                                     n_exprs);
     806                 :          32 :   compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout);
     807                 :             : 
     808                 :             : #ifdef LCM_DEBUG_INFO
     809                 :             :   if (dump_file)
     810                 :             :     {
     811                 :             :       dump_bitmap_vector (dump_file, "nearerout", "", nearerout,
     812                 :             :                            last_basic_block_for_fn (cfun) + 1);
     813                 :             :       dump_bitmap_vector (dump_file, "nearer", "", nearer, num_edges);
     814                 :             :     }
     815                 :             : #endif
     816                 :             : 
     817                 :          32 :   sbitmap_vector_free (farthest);
     818                 :             : 
     819                 :          32 :   *insert = sbitmap_vector_alloc (num_edges, n_exprs);
     820                 :          32 :   *del = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     821                 :          32 :   compute_rev_insert_delete (edge_list, st_avloc, nearer, nearerout,
     822                 :             :                              *insert, *del);
     823                 :             : 
     824                 :          32 :   sbitmap_vector_free (nearerout);
     825                 :          32 :   sbitmap_vector_free (nearer);
     826                 :             : 
     827                 :             : #ifdef LCM_DEBUG_INFO
     828                 :             :   if (dump_file)
     829                 :             :     {
     830                 :             :       dump_bitmap_vector (dump_file, "pre_insert_map", "", *insert, num_edges);
     831                 :             :       dump_bitmap_vector (dump_file, "pre_delete_map", "", *del,
     832                 :             :                            last_basic_block_for_fn (cfun));
     833                 :             :     }
     834                 :             : #endif
     835                 :          32 :   return edge_list;
     836                 :             : }
     837                 :             : 
        

Generated by: LCOV version 2.1-beta

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