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: 2026-02-28 14:20:25 Functions: 100.0 % 11 11
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Generic partial redundancy elimination with lazy code motion support.
       2              :    Copyright (C) 1998-2026 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       493065 : compute_antinout_edge (sbitmap *antloc, sbitmap *transp, sbitmap *antin,
      81              :                        sbitmap *antout)
      82              : {
      83       493065 :   basic_block bb;
      84       493065 :   edge e;
      85       493065 :   basic_block *worklist, *qin, *qout, *qend;
      86       493065 :   unsigned int qlen;
      87       493065 :   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       493065 :   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       493065 :   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       493065 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
     103       493065 :   int n = inverted_rev_post_order_compute (cfun, rpo);
     104     11133608 :   for (int i = 0; i < n; ++i)
     105              :     {
     106     10640543 :       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
     107     10640543 :       if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
     108     10147478 :           || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     109       986130 :         continue;
     110      9654413 :       *qin++ = bb;
     111      9654413 :       bb->aux = bb;
     112              :     }
     113       493065 :   free (rpo);
     114              : 
     115       493065 :   qin = worklist;
     116       493065 :   qend = &worklist[n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS];
     117       493065 :   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      1419024 :   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
     122       925959 :     e->src->aux = EXIT_BLOCK_PTR_FOR_FN (cfun);
     123              : 
     124              :   /* Iterate until the worklist is empty.  */
     125     11158734 :   while (qlen)
     126              :     {
     127              :       /* Take the first entry off the worklist.  */
     128     10665669 :       bb = *qout++;
     129     10665669 :       qlen--;
     130              : 
     131     10665669 :       if (qout >= qend)
     132       493814 :         qout = worklist;
     133              : 
     134     10665669 :       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       925959 :         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      9739710 :           bb->aux = NULL;
     144      9739710 :           bitmap_intersection_of_succs (antout[bb->index], antin, bb);
     145              :         }
     146              : 
     147     10665669 :       if (bitmap_or_and (antin[bb->index], antloc[bb->index],
     148     10665669 :                                    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     24531644 :         FOR_EACH_EDGE (e, ei, bb->preds)
     153     14649289 :           if (!e->src->aux && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
     154              :             {
     155      1011256 :               *qin++ = e->src;
     156      1011256 :               e->src->aux = e;
     157      1011256 :               qlen++;
     158      1011256 :               if (qin >= qend)
     159          749 :                 qin = worklist;
     160              :             }
     161              :     }
     162              : 
     163       493065 :   clear_aux_for_edges ();
     164       493065 :   clear_aux_for_blocks ();
     165       493065 :   free (worklist);
     166       493065 : }
     167              : 
     168              : /* Compute the earliest vector for edge based lcm.  */
     169              : 
     170              : void
     171       493033 : compute_earliest (struct edge_list *edge_list, int n_exprs, sbitmap *antin,
     172              :                   sbitmap *antout, sbitmap *avout, sbitmap *kill,
     173              :                   sbitmap *earliest)
     174              : {
     175       493033 :   int x, num_edges;
     176       493033 :   basic_block pred, succ;
     177              : 
     178       493033 :   num_edges = NUM_EDGES (edge_list);
     179              : 
     180       493033 :   auto_sbitmap difference (n_exprs), temp_bitmap (n_exprs);
     181     16227864 :   for (x = 0; x < num_edges; x++)
     182              :     {
     183     15241798 :       pred = INDEX_EDGE_PRED_BB (edge_list, x);
     184     15241798 :       succ = INDEX_EDGE_SUCC_BB (edge_list, x);
     185     15241798 :       if (pred == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     186       493033 :         bitmap_copy (earliest[x], antin[succ->index]);
     187              :       else
     188              :         {
     189     14748765 :           if (succ == EXIT_BLOCK_PTR_FOR_FN (cfun))
     190       925926 :             bitmap_clear (earliest[x]);
     191              :           else
     192              :             {
     193     13822839 :               bitmap_and_compl (difference, antin[succ->index],
     194     13822839 :                                   avout[pred->index]);
     195     13822839 :               bitmap_not (temp_bitmap, antout[pred->index]);
     196     13822839 :               bitmap_and_or (earliest[x], difference,
     197     13822839 :                                     kill[pred->index], temp_bitmap);
     198              :             }
     199              :         }
     200              :     }
     201       493033 : }
     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       493033 : compute_laterin (struct edge_list *edge_list, sbitmap *earliest,
     234              :                  sbitmap *antloc, sbitmap *later, sbitmap *laterin)
     235              : {
     236       493033 :   int num_edges, i;
     237       493033 :   edge e;
     238       493033 :   basic_block *worklist, *qin, *qout, *qend, bb;
     239       493033 :   unsigned int qlen;
     240       493033 :   edge_iterator ei;
     241              : 
     242       493033 :   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       493033 :   qin = qout = worklist
     248       493033 :     = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
     249              : 
     250              :   /* Initialize a mapping from each edge to its index.  */
     251     16227864 :   for (i = 0; i < num_edges; i++)
     252     15241798 :     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       493033 :   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       986066 :   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     271       493033 :     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       493033 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
     276       493033 :   int n = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, false);
     277     10147298 :   for (int i = 0; i < n; ++i)
     278              :     {
     279      9654265 :       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
     280      9654265 :       *qin++ = bb;
     281      9654265 :       bb->aux = bb;
     282              :     }
     283       493033 :   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       493033 :   qin = worklist;
     288       493033 :   qend = &worklist[n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS];
     289       493033 :   qlen = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
     290              : 
     291              :   /* Iterate until the worklist is empty.  */
     292     10884755 :   while (qlen)
     293              :     {
     294              :       /* Take the first entry off the worklist.  */
     295     10391722 :       bb = *qout++;
     296     10391722 :       bb->aux = NULL;
     297     10391722 :       qlen--;
     298     10391722 :       if (qout >= qend)
     299       493390 :         qout = worklist;
     300              : 
     301              :       /* Compute LATERIN as the intersection of LATER for each incoming
     302              :          edge to BB.  */
     303     10391722 :       bitmap_ones (laterin[bb->index]);
     304     26291951 :       FOR_EACH_EDGE (e, ei, bb->preds)
     305     15900229 :         bitmap_and (laterin[bb->index], laterin[bb->index],
     306     15900229 :                     later[(size_t)e->aux]);
     307              : 
     308              :       /* Calculate LATER for all outgoing edges of BB.  */
     309     26514808 :       FOR_EACH_EDGE (e, ei, bb->succs)
     310     16123086 :         if (bitmap_ior_and_compl (later[(size_t) e->aux],
     311     16123086 :                                   earliest[(size_t) e->aux],
     312     16123086 :                                   laterin[bb->index],
     313     16123086 :                                   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     16123086 :             && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun) && e->dest->aux == 0)
     317              :           {
     318       737457 :             *qin++ = e->dest;
     319       737457 :             e->dest->aux = e;
     320       737457 :             qlen++;
     321       737457 :             if (qin >= qend)
     322          357 :               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       493033 :   bitmap_ones (laterin[last_basic_block_for_fn (cfun)]);
     330      1418959 :   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
     331       925926 :     bitmap_and (laterin[last_basic_block_for_fn (cfun)],
     332       925926 :                 laterin[last_basic_block_for_fn (cfun)],
     333       925926 :                 later[(size_t) e->aux]);
     334              : 
     335       493033 :   clear_aux_for_edges ();
     336       493033 :   free (worklist);
     337       493033 : }
     338              : 
     339              : /* Compute the insertion and deletion points for edge based LCM.  */
     340              : 
     341              : static void
     342       493033 : compute_insert_delete (struct edge_list *edge_list, sbitmap *antloc,
     343              :                        sbitmap *later, sbitmap *laterin, sbitmap *insert,
     344              :                        sbitmap *del)
     345              : {
     346       493033 :   int x;
     347       493033 :   basic_block bb;
     348              : 
     349     10147298 :   FOR_EACH_BB_FN (bb, cfun)
     350      9654265 :     bitmap_and_compl (del[bb->index], antloc[bb->index],
     351      9654265 :                         laterin[bb->index]);
     352              : 
     353     15734831 :   for (x = 0; x < NUM_EDGES (edge_list); x++)
     354              :     {
     355     15241798 :       basic_block b = INDEX_EDGE_SUCC_BB (edge_list, x);
     356              : 
     357     15241798 :       if (b == EXIT_BLOCK_PTR_FOR_FN (cfun))
     358       925926 :         bitmap_and_compl (insert[x], later[x],
     359       925926 :                           laterin[last_basic_block_for_fn (cfun)]);
     360              :       else
     361     14315872 :         bitmap_and_compl (insert[x], later[x], laterin[b->index]);
     362              :     }
     363       493033 : }
     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       493033 : 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       493033 :   sbitmap *antin, *antout, *earliest;
     376       493033 :   sbitmap *later, *laterin;
     377       493033 :   struct edge_list *edge_list;
     378       493033 :   int num_edges;
     379              : 
     380       493033 :   edge_list = create_edge_list ();
     381       493033 :   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       493033 :   compute_available (avloc, kill, avout, avin);
     402              : 
     403              :   /* Compute global anticipatability.  */
     404       493033 :   antin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     405       493033 :   antout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     406       493033 :   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       493033 :   earliest = sbitmap_vector_alloc (num_edges, n_exprs);
     420       493033 :   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       493033 :   sbitmap_vector_free (antout);
     428       493033 :   sbitmap_vector_free (antin);
     429              : 
     430       493033 :   later = sbitmap_vector_alloc (num_edges, n_exprs);
     431              : 
     432              :   /* Allocate an extra element for the exit block in the laterin vector.  */
     433       493033 :   laterin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun) + 1,
     434              :                                   n_exprs);
     435       493033 :   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       493033 :   sbitmap_vector_free (earliest);
     447              : 
     448       493033 :   *insert = sbitmap_vector_alloc (num_edges, n_exprs);
     449       493033 :   *del = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     450       493033 :   bitmap_vector_clear (*insert, num_edges);
     451       493033 :   bitmap_vector_clear (*del, last_basic_block_for_fn (cfun));
     452       493033 :   compute_insert_delete (edge_list, antloc, later, laterin, *insert, *del);
     453              : 
     454       493033 :   sbitmap_vector_free (laterin);
     455       493033 :   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       493033 :   return edge_list;
     467              : }
     468              : 
     469              : /* Wrapper to allocate avin/avout and call pre_edge_lcm_avs.  */
     470              : 
     471              : struct edge_list *
     472       417337 : pre_edge_lcm (int n_exprs, sbitmap *transp,
     473              :               sbitmap *avloc, sbitmap *antloc, sbitmap *kill,
     474              :               sbitmap **insert, sbitmap **del)
     475              : {
     476       417337 :   struct edge_list *edge_list;
     477       417337 :   sbitmap *avin, *avout;
     478              : 
     479       417337 :   avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     480       417337 :   avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_exprs);
     481              : 
     482       417337 :   edge_list = pre_edge_lcm_avs (n_exprs, transp, avloc, antloc, kill,
     483              :                                  avin, avout, insert, del);
     484              : 
     485       417337 :   sbitmap_vector_free (avout);
     486       417337 :   sbitmap_vector_free (avin);
     487              : 
     488       417337 :   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      1855674 : compute_available (sbitmap *avloc, sbitmap *kill, sbitmap *avout,
     496              :                    sbitmap *avin)
     497              : {
     498      1855674 :   edge e;
     499      1855674 :   basic_block *worklist, *qin, *qout, *qend, bb;
     500      1855674 :   unsigned int qlen;
     501      1855674 :   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      3711348 :   qin = qout = worklist =
     507      1855674 :     XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
     508              : 
     509              :   /* We want a maximal solution.  */
     510      1855674 :   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      1855674 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
     516      1855674 :   int n = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, false);
     517     42368955 :   for (int i = 0; i < n; ++i)
     518              :     {
     519     40513281 :       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
     520     40513281 :       *qin++ = bb;
     521     40513281 :       bb->aux = bb;
     522              :     }
     523      1855674 :   free (rpo);
     524              : 
     525      1855674 :   qin = worklist;
     526      1855674 :   qend = &worklist[n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS];
     527      1855674 :   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      3711348 :   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     532      1855674 :     e->dest->aux = ENTRY_BLOCK_PTR_FOR_FN (cfun);
     533              : 
     534              :   /* Iterate until the worklist is empty.  */
     535     60201093 :   while (qlen)
     536              :     {
     537              :       /* Take the first entry off the worklist.  */
     538     58345419 :       bb = *qout++;
     539     58345419 :       qlen--;
     540              : 
     541     58345419 :       if (qout >= qend)
     542      1973151 :         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     58345419 :       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      1855674 :         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     56489745 :           bb->aux = NULL;
     556     56489745 :           bitmap_intersection_of_preds (avin[bb->index], avout, bb);
     557              :         }
     558              : 
     559     58345419 :       if (bitmap_ior_and_compl (avout[bb->index], avloc[bb->index],
     560     58345419 :                                     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    128311537 :         FOR_EACH_EDGE (e, ei, bb->succs)
     565     76856740 :           if (!e->dest->aux && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
     566              :             {
     567     17832138 :               *qin++ = e->dest;
     568     17832138 :               e->dest->aux = e;
     569     17832138 :               qlen++;
     570              : 
     571     17832138 :               if (qin >= qend)
     572       117477 :                 qin = worklist;
     573              :             }
     574              :     }
     575              : 
     576      1855674 :   clear_aux_for_edges ();
     577      1855674 :   clear_aux_for_blocks ();
     578      1855674 :   free (worklist);
     579      1855674 : }
     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          305 :   for (x = 0; x < num_edges; x++)
     595              :     {
     596          241 :       pred = INDEX_EDGE_PRED_BB (edge_list, x);
     597          241 :       succ = INDEX_EDGE_SUCC_BB (edge_list, x);
     598          241 :       if (succ == EXIT_BLOCK_PTR_FOR_FN (cfun))
     599           33 :         bitmap_copy (farthest[x], st_avout[pred->index]);
     600              :       else
     601              :         {
     602          208 :           if (pred == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     603           32 :             bitmap_clear (farthest[x]);
     604              :           else
     605              :             {
     606          176 :               bitmap_and_compl (difference, st_avout[pred->index],
     607          176 :                                   st_antin[succ->index]);
     608          176 :               bitmap_not (temp_bitmap, st_avin[succ->index]);
     609          176 :               bitmap_and_or (farthest[x], difference,
     610          176 :                                     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          305 :   for (i = 0; i < num_edges; i++)
     640          241 :     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          180 :   FOR_EACH_BB_FN (bb, cfun)
     655              :     {
     656          148 :       *tos++ = bb;
     657          148 :       bb->aux = bb;
     658              :     }
     659              : 
     660              :   /* Iterate until the worklist is empty.  */
     661          202 :   while (tos != worklist)
     662              :     {
     663              :       /* Take the first entry off the worklist.  */
     664          170 :       bb = *--tos;
     665          170 :       bb->aux = NULL;
     666              : 
     667              :       /* Compute the intersection of NEARER for each outgoing edge from B.  */
     668          170 :       bitmap_ones (nearerout[bb->index]);
     669          418 :       FOR_EACH_EDGE (e, ei, bb->succs)
     670          248 :         bitmap_and (nearerout[bb->index], nearerout[bb->index],
     671          248 :                          nearer[(size_t) e->aux]);
     672              : 
     673              :       /* Calculate NEARER for all incoming edges.  */
     674          412 :       FOR_EACH_EDGE (e, ei, bb->preds)
     675          242 :         if (bitmap_ior_and_compl (nearer[(size_t) e->aux],
     676          242 :                                       farthest[(size_t) e->aux],
     677          242 :                                       nearerout[e->dest->index],
     678          242 :                                       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          242 :             && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun) && e->src->aux == 0)
     682              :           {
     683           22 :             *tos++ = e->src;
     684           22 :             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          180 :   FOR_EACH_BB_FN (bb, cfun)
     712          148 :     bitmap_and_compl (del[bb->index], st_avloc[bb->index],
     713          148 :                         nearerout[bb->index]);
     714              : 
     715          273 :   for (x = 0; x < NUM_EDGES (edge_list); x++)
     716              :     {
     717          241 :       basic_block b = INDEX_EDGE_PRED_BB (edge_list, x);
     718          241 :       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          209 :         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.4-beta

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