LCOV - code coverage report
Current view: top level - gcc - gcse-common.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.3 % 89 83
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Shared code for before and after reload gcse implementations.
       2              :    Copyright (C) 1997-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              :    It is expected that more hunks of gcse.cc and postreload-gcse.cc should
      21              :    migrate into this file.  */
      22              : 
      23              : #include "config.h"
      24              : #include "system.h"
      25              : #include "coretypes.h"
      26              : #include "backend.h"
      27              : #include "rtl.h"
      28              : #include "df.h"
      29              : #include "gcse-common.h"
      30              : #include "regs.h"
      31              : #include "function-abi.h"
      32              : 
      33              : /* Record all of the canonicalized MEMs of record_last_mem_set_info's insn.
      34              :    Note we store a pair of elements in the list, so they have to be
      35              :    taken off pairwise.  */
      36              : 
      37              : void
      38      7362807 : canon_list_insert (rtx dest, const_rtx x ATTRIBUTE_UNUSED, void *data)
      39              : {
      40      7362807 :   rtx dest_addr;
      41      7362807 :   int bb;
      42      7362807 :   modify_pair pair;
      43              : 
      44      7362807 :   while (GET_CODE (dest) == SUBREG
      45      7362807 :       || GET_CODE (dest) == ZERO_EXTRACT
      46     14725614 :       || GET_CODE (dest) == STRICT_LOW_PART)
      47            0 :     dest = XEXP (dest, 0);
      48              : 
      49              :   /* If DEST is not a MEM, then it will not conflict with a load.  Note
      50              :      that function calls are assumed to clobber memory, but are handled
      51              :      elsewhere.  */
      52              : 
      53      7362807 :   if (! MEM_P (dest))
      54       290837 :     return;
      55              : 
      56      7071970 :   dest_addr = get_addr (XEXP (dest, 0));
      57      7071970 :   dest_addr = canon_rtx (dest_addr);
      58      7071970 :   rtx_insn *insn = ((struct gcse_note_stores_info *)data)->insn;
      59      7071970 :   bb = BLOCK_FOR_INSN (insn)->index;
      60              : 
      61      7071970 :   pair.dest = dest;
      62      7071970 :   pair.dest_addr = dest_addr;
      63      7071970 :   vec<modify_pair> *canon_mem_list
      64              :     = ((struct gcse_note_stores_info *)data)->canon_mem_list;
      65      7071970 :   canon_mem_list[bb].safe_push (pair);
      66              : }
      67              : 
      68              : /* Record memory modification information for INSN.  We do not actually care
      69              :    about the memory location(s) that are set, or even how they are set (consider
      70              :    a CALL_INSN).  We merely need to record which insns modify memory.  */
      71              : 
      72              : void
      73     10945060 : record_last_mem_set_info_common (rtx_insn *insn,
      74              :                                  vec<rtx_insn *> *modify_mem_list,
      75              :                                  vec<modify_pair> *canon_modify_mem_list,
      76              :                                  bitmap modify_mem_list_set,
      77              :                                  bitmap blocks_with_calls)
      78              : 
      79              : {
      80     10945060 :   int bb;
      81              : 
      82     10945060 :   bb = BLOCK_FOR_INSN (insn)->index;
      83     10945060 :   modify_mem_list[bb].safe_push (insn);
      84     10945060 :   bitmap_set_bit (modify_mem_list_set, bb);
      85              : 
      86     10945060 :   if (CALL_P (insn))
      87      3873996 :     bitmap_set_bit (blocks_with_calls, bb);
      88              :   else
      89              :     {
      90      7071064 :       struct gcse_note_stores_info data;
      91      7071064 :       data.insn = insn;
      92      7071064 :       data.canon_mem_list = canon_modify_mem_list;
      93      7071064 :       note_stores (insn, canon_list_insert, (void*) &data);
      94              :     }
      95     10945060 : }
      96              : 
      97              : 
      98              : /* For each block, compute whether X is transparent.  X is either an
      99              :    expression or an assignment [though we don't care which, for this context
     100              :    an assignment is treated as an expression].  For each block where an
     101              :    element of X is modified, reset the INDX bit in BMAP.
     102              : 
     103              :    BLOCKS_WITH_CALLS indicates which blocks contain CALL_INSNs which kill
     104              :    memory.
     105              : 
     106              :    MODIFY_MEM_LIST_SET indicates which blocks have memory stores which might
     107              :    kill a particular memory location.
     108              : 
     109              :    CANON_MODIFY_MEM_LIST is the canonicalized list of memory locations modified
     110              :    for each block.  */
     111              : 
     112              : void
     113     20010278 : compute_transp (const_rtx x, int indx, sbitmap *bmap,
     114              :                 bitmap blocks_with_calls,
     115              :                 bitmap modify_mem_list_set,
     116              :                 vec<modify_pair> *canon_modify_mem_list)
     117              : {
     118     34764007 :   int i, j;
     119     34764007 :   enum rtx_code code;
     120     34764007 :   const char *fmt;
     121              : 
     122              :   /* repeat is used to turn tail-recursion into iteration since GCC
     123              :      can't do it when there's no return value.  */
     124     34764007 :  repeat:
     125              : 
     126     34764007 :   if (x == 0)
     127              :     return;
     128              : 
     129     34764007 :   code = GET_CODE (x);
     130     34764007 :   switch (code)
     131              :     {
     132     11907340 :     case REG:
     133     11907340 :       {
     134     11907340 :         df_ref def;
     135     11907340 :         for (def = DF_REG_DEF_CHAIN (REGNO (x));
     136     78456760 :              def;
     137     66549420 :              def = DF_REF_NEXT_REG (def))
     138     66549420 :           bitmap_clear_bit (bmap[DF_REF_BB (def)->index], indx);
     139              : 
     140              :         /* Check for hard registers that are partially clobbered (but not
     141              :            fully clobbered) by calls.  Such partial clobbers do not have
     142              :            an associated definition or use in the DF representation,
     143              :            but they do prevent the register from being transparent.
     144              : 
     145              :            ??? The check here is fairly crude.  We could instead maintain
     146              :            separate blocks_with_calls bitmaps for each ABI.  */
     147     11907340 :         if (HARD_REGISTER_P (x))
     148     32595303 :           for (unsigned int i = 0; i < NUM_ABI_IDS; ++i)
     149              :             {
     150     30087972 :               const predefined_function_abi &abi = function_abis[i];
     151     30087972 :               if (abi.initialized_p ()
     152     32621139 :                   && overlaps_hard_reg_set_p (abi.only_partial_reg_clobbers (),
     153      2533167 :                                               GET_MODE (x), REGNO (x)))
     154              :                 {
     155            0 :                   bitmap_iterator bi;
     156            0 :                   unsigned bb_index;
     157            0 :                   EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
     158            0 :                     bitmap_clear_bit (bmap[bb_index], indx);
     159            0 :                   break;
     160              :                 }
     161              :             }
     162              :       }
     163              : 
     164              :       return;
     165              : 
     166      4670288 :     case MEM:
     167      4670288 :       if (! MEM_READONLY_P (x))
     168              :         {
     169      4302419 :           bitmap_iterator bi;
     170      4302419 :           unsigned bb_index;
     171      4302419 :           rtx x_addr;
     172              : 
     173      4302419 :           x_addr = get_addr (XEXP (x, 0));
     174      4302419 :           x_addr = canon_rtx (x_addr);
     175              : 
     176              :           /* First handle all the blocks with calls.  We don't need to
     177              :              do any list walking for them.  */
     178    149339332 :           EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
     179              :             {
     180    145036913 :               bitmap_clear_bit (bmap[bb_index], indx);
     181              :             }
     182              : 
     183              :           /* Now iterate over the blocks which have memory modifications
     184              :              but which do not have any calls.  */
     185    110014787 :           EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set,
     186              :                                           blocks_with_calls,
     187              :                                           0, bb_index, bi)
     188              :             {
     189    105712368 :               vec<modify_pair> list
     190    105712368 :                 = canon_modify_mem_list[bb_index];
     191    105712368 :               modify_pair *pair;
     192    105712368 :               unsigned ix;
     193              : 
     194    464553845 :               FOR_EACH_VEC_ELT_REVERSE (list, ix, pair)
     195              :                 {
     196    191517148 :                   rtx dest = pair->dest;
     197    191517148 :                   rtx dest_addr = pair->dest_addr;
     198              : 
     199    191517148 :                   if (canon_true_dependence (dest, GET_MODE (dest),
     200              :                                              dest_addr, x, x_addr))
     201              :                     {
     202     44100407 :                       bitmap_clear_bit (bmap[bb_index], indx);
     203     44100407 :                       break;
     204              :                     }
     205              :                 }
     206              :             }
     207              :         }
     208              : 
     209      4670288 :       x = XEXP (x, 0);
     210      4670288 :       goto repeat;
     211              : 
     212              :     case PC:
     213              :     case CONST:
     214              :     CASE_CONST_ANY:
     215              :     case SYMBOL_REF:
     216              :     case LABEL_REF:
     217              :     case ADDR_VEC:
     218              :     case ADDR_DIFF_VEC:
     219              :       return;
     220              : 
     221     10327966 :     default:
     222     10327966 :       break;
     223              :     }
     224              : 
     225     19775680 :   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
     226              :     {
     227     19531155 :       if (fmt[i] == 'e')
     228              :         {
     229              :           /* If we are about to do the last recursive call
     230              :              needed at this level, change it into iteration.
     231              :              This function is called enough to be worth it.  */
     232     18939529 :           if (i == 0)
     233              :             {
     234     10083441 :               x = XEXP (x, i);
     235     10083441 :               goto repeat;
     236              :             }
     237              : 
     238      8856088 :           compute_transp (XEXP (x, i), indx, bmap, blocks_with_calls,
     239              :                           modify_mem_list_set, canon_modify_mem_list);
     240              :         }
     241       591626 :       else if (fmt[i] == 'E')
     242      1073951 :         for (j = 0; j < XVECLEN (x, i); j++)
     243       829426 :           compute_transp (XVECEXP (x, i, j), indx, bmap, blocks_with_calls,
     244              :                           modify_mem_list_set, canon_modify_mem_list);
     245              :     }
     246              : }
        

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.