LCOV - code coverage report
Current view: top level - gcc - valtrack.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.2 % 351 320
Test Date: 2024-03-23 14:05:01 Functions: 100.0 % 16 16
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Infrastructure for tracking user variable locations and values
       2                 :             :    throughout compilation.
       3                 :             :    Copyright (C) 2010-2024 Free Software Foundation, Inc.
       4                 :             :    Contributed by Alexandre Oliva <aoliva@redhat.com>.
       5                 :             : 
       6                 :             : This file is part of GCC.
       7                 :             : 
       8                 :             : GCC is free software; you can redistribute it and/or modify it under
       9                 :             : the terms of the GNU General Public License as published by the Free
      10                 :             : Software Foundation; either version 3, or (at your option) any later
      11                 :             : version.
      12                 :             : 
      13                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16                 :             : for more details.
      17                 :             : 
      18                 :             : You should have received a copy of the GNU General Public License
      19                 :             : along with GCC; see the file COPYING3.  If not see
      20                 :             : <http://www.gnu.org/licenses/>.  */
      21                 :             : 
      22                 :             : #include "config.h"
      23                 :             : #include "system.h"
      24                 :             : #include "coretypes.h"
      25                 :             : #include "backend.h"
      26                 :             : #include "rtl.h"
      27                 :             : #include "df.h"
      28                 :             : #include "valtrack.h"
      29                 :             : #include "regs.h"
      30                 :             : #include "memmodel.h"
      31                 :             : #include "emit-rtl.h"
      32                 :             : #include "rtl-iter.h"
      33                 :             : 
      34                 :             : /* gen_lowpart_no_emit hook implementation for DEBUG_INSNs.  In DEBUG_INSNs,
      35                 :             :    all lowpart SUBREGs are valid, despite what the machine requires for
      36                 :             :    instructions.  */
      37                 :             : 
      38                 :             : static rtx
      39                 :         170 : gen_lowpart_for_debug (machine_mode mode, rtx x)
      40                 :             : {
      41                 :         170 :   rtx result = gen_lowpart_if_possible (mode, x);
      42                 :         170 :   if (result)
      43                 :             :     return result;
      44                 :             : 
      45                 :           0 :   if (GET_MODE (x) != VOIDmode)
      46                 :           0 :     return gen_rtx_raw_SUBREG (mode, x,
      47                 :             :                                subreg_lowpart_offset (mode, GET_MODE (x)));
      48                 :             : 
      49                 :             :   return NULL_RTX;
      50                 :             : }
      51                 :             : 
      52                 :             : /* Replace auto-increment addressing modes with explicit operations to access
      53                 :             :    the same addresses without modifying the corresponding registers.  */
      54                 :             : 
      55                 :             : static rtx
      56                 :      995502 : cleanup_auto_inc_dec (rtx src, machine_mode mem_mode ATTRIBUTE_UNUSED)
      57                 :             : {
      58                 :      995502 :   rtx x = src;
      59                 :             : 
      60                 :      995502 :   const RTX_CODE code = GET_CODE (x);
      61                 :      995502 :   int i;
      62                 :      995502 :   const char *fmt;
      63                 :             : 
      64                 :      995502 :   switch (code)
      65                 :             :     {
      66                 :             :     case REG:
      67                 :             :     CASE_CONST_ANY:
      68                 :             :     case SYMBOL_REF:
      69                 :             :     case CODE_LABEL:
      70                 :             :     case PC:
      71                 :             :     case SCRATCH:
      72                 :             :       /* SCRATCH must be shared because they represent distinct values.  */
      73                 :             :       return x;
      74                 :           0 :     case CLOBBER:
      75                 :             :       /* Share clobbers of hard registers, but do not share pseudo reg
      76                 :             :          clobbers or clobbers of hard registers that originated as pseudos.
      77                 :             :          This is needed to allow safe register renaming.  */
      78                 :           0 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
      79                 :           0 :           && ORIGINAL_REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 0)))
      80                 :             :         return x;
      81                 :             :       break;
      82                 :             : 
      83                 :        1665 :     case CONST:
      84                 :        1665 :       if (shared_const_p (x))
      85                 :             :         return x;
      86                 :             :       break;
      87                 :             : 
      88                 :       93265 :     case MEM:
      89                 :       93265 :       mem_mode = GET_MODE (x);
      90                 :       93265 :       break;
      91                 :             : 
      92                 :           0 :     case PRE_INC:
      93                 :           0 :     case PRE_DEC:
      94                 :           0 :       {
      95                 :           0 :         gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode);
      96                 :           0 :         poly_int64 offset = GET_MODE_SIZE (mem_mode);
      97                 :           0 :         if (code == PRE_DEC)
      98                 :           0 :           offset = -offset;
      99                 :           0 :         return gen_rtx_PLUS (GET_MODE (x),
     100                 :             :                              cleanup_auto_inc_dec (XEXP (x, 0), mem_mode),
     101                 :             :                              gen_int_mode (offset, GET_MODE (x)));
     102                 :             :       }
     103                 :             : 
     104                 :           0 :     case POST_INC:
     105                 :           0 :     case POST_DEC:
     106                 :           0 :     case PRE_MODIFY:
     107                 :           0 :     case POST_MODIFY:
     108                 :           0 :       return cleanup_auto_inc_dec (code == PRE_MODIFY
     109                 :             :                                    ? XEXP (x, 1) : XEXP (x, 0),
     110                 :           0 :                                    mem_mode);
     111                 :             : 
     112                 :             :     default:
     113                 :             :       break;
     114                 :             :     }
     115                 :             : 
     116                 :             :   /* Copy the various flags, fields, and other information.  We assume
     117                 :             :      that all fields need copying, and then clear the fields that should
     118                 :             :      not be copied.  That is the sensible default behavior, and forces
     119                 :             :      us to explicitly document why we are *not* copying a flag.  */
     120                 :      323381 :   x = shallow_copy_rtx (x);
     121                 :             : 
     122                 :             :   /* We do not copy FRAME_RELATED for INSNs.  */
     123                 :      323381 :   if (INSN_P (x))
     124                 :           0 :     RTX_FLAG (x, frame_related) = 0;
     125                 :             : 
     126                 :      323381 :   fmt = GET_RTX_FORMAT (code);
     127                 :      963904 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     128                 :      640523 :     if (fmt[i] == 'e')
     129                 :      536092 :       XEXP (x, i) = cleanup_auto_inc_dec (XEXP (x, i), mem_mode);
     130                 :      104431 :     else if (fmt[i] == 'E' || fmt[i] == 'V')
     131                 :             :       {
     132                 :         556 :         int j;
     133                 :         556 :         XVEC (x, i) = rtvec_alloc (XVECLEN (x, i));
     134                 :        1116 :         for (j = 0; j < XVECLEN (x, i); j++)
     135                 :         560 :           XVECEXP (x, i, j)
     136                 :         560 :             = cleanup_auto_inc_dec (XVECEXP (src, i, j), mem_mode);
     137                 :             :       }
     138                 :             : 
     139                 :             :   return x;
     140                 :             : }
     141                 :             : 
     142                 :             : /* Auxiliary data structure for propagate_for_debug_stmt.  */
     143                 :             : 
     144                 :             : struct rtx_subst_pair
     145                 :             : {
     146                 :             :   rtx to;
     147                 :             :   bool adjusted;
     148                 :             :   rtx_insn *insn;
     149                 :             : };
     150                 :             : 
     151                 :             : /* DATA points to an rtx_subst_pair.  Return the value that should be
     152                 :             :    substituted.  */
     153                 :             : 
     154                 :             : static rtx
     155                 :     2670181 : propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data)
     156                 :             : {
     157                 :     2670181 :   struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
     158                 :             : 
     159                 :     2670181 :   if (!rtx_equal_p (from, old_rtx))
     160                 :             :     return NULL_RTX;
     161                 :      246033 :   if (!pair->adjusted)
     162                 :             :     {
     163                 :      203167 :       pair->adjusted = true;
     164                 :      203167 :       pair->to = cleanup_auto_inc_dec (pair->to, VOIDmode);
     165                 :      203167 :       pair->to = make_compound_operation (pair->to, SET);
     166                 :             :       /* Avoid propagation from growing DEBUG_INSN expressions too much.  */
     167                 :      203167 :       int cnt = 0;
     168                 :      203167 :       subrtx_iterator::array_type array;
     169                 :      617644 :       FOR_EACH_SUBRTX (iter, array, pair->to, ALL)
     170                 :      436151 :         if (REG_P (*iter) && ++cnt > 1)
     171                 :             :           {
     172                 :       21674 :             rtx dval = make_debug_expr_from_rtl (old_rtx);
     173                 :       21674 :             rtx to = pair->to;
     174                 :       21674 :             if (volatile_insn_p (to))
     175                 :           0 :               to = gen_rtx_UNKNOWN_VAR_LOC ();
     176                 :             :             /* Emit a debug bind insn.  */
     177                 :       21674 :             rtx bind
     178                 :       21674 :               = gen_rtx_VAR_LOCATION (GET_MODE (old_rtx),
     179                 :             :                                       DEBUG_EXPR_TREE_DECL (dval), to,
     180                 :             :                                       VAR_INIT_STATUS_INITIALIZED);
     181                 :       21674 :             rtx_insn *bind_insn = emit_debug_insn_before (bind, pair->insn);
     182                 :       21674 :             df_insn_rescan (bind_insn);
     183                 :       21674 :             pair->to = dval;
     184                 :       21674 :             break;
     185                 :             :           }
     186                 :      203167 :       return pair->to;
     187                 :      203167 :     }
     188                 :       42866 :   return copy_rtx (pair->to);
     189                 :             : }
     190                 :             : 
     191                 :             : /* Replace all the occurrences of DEST with SRC in DEBUG_INSNs between INSN
     192                 :             :    and LAST, not including INSN, but including LAST.  Also stop at the end
     193                 :             :    of THIS_BASIC_BLOCK.  */
     194                 :             : 
     195                 :             : void
     196                 :     1960949 : propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src,
     197                 :             :                      basic_block this_basic_block)
     198                 :             : {
     199                 :     1960949 :   rtx_insn *next, *end = NEXT_INSN (BB_END (this_basic_block));
     200                 :     1960949 :   rtx loc;
     201                 :     1960949 :   rtx (*saved_rtl_hook_no_emit) (machine_mode, rtx);
     202                 :             : 
     203                 :     1960949 :   struct rtx_subst_pair p;
     204                 :     1960949 :   p.to = src;
     205                 :     1960949 :   p.adjusted = false;
     206                 :     1960949 :   p.insn = NEXT_INSN (insn);
     207                 :             : 
     208                 :     1960949 :   next = NEXT_INSN (insn);
     209                 :     1960949 :   last = NEXT_INSN (last);
     210                 :     1960949 :   saved_rtl_hook_no_emit = rtl_hooks.gen_lowpart_no_emit;
     211                 :     1960949 :   rtl_hooks.gen_lowpart_no_emit = gen_lowpart_for_debug;
     212                 :     7794373 :   while (next != last && next != end)
     213                 :             :     {
     214                 :     5833424 :       insn = next;
     215                 :     5833424 :       next = NEXT_INSN (insn);
     216                 :     5833424 :       if (DEBUG_BIND_INSN_P (insn))
     217                 :             :         {
     218                 :     1494507 :           loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn),
     219                 :             :                                          dest, propagate_for_debug_subst, &p);
     220                 :     1494507 :           if (loc == INSN_VAR_LOCATION_LOC (insn))
     221                 :     1248767 :             continue;
     222                 :      245740 :           if (volatile_insn_p (loc))
     223                 :           0 :             loc = gen_rtx_UNKNOWN_VAR_LOC ();
     224                 :      245740 :           INSN_VAR_LOCATION_LOC (insn) = loc;
     225                 :      245740 :           df_insn_rescan (insn);
     226                 :             :         }
     227                 :             :     }
     228                 :     1960949 :   rtl_hooks.gen_lowpart_no_emit = saved_rtl_hook_no_emit;
     229                 :     1960949 : }
     230                 :             : 
     231                 :             : /* Initialize DEBUG to an empty list, and clear USED, if given.  */
     232                 :             : 
     233                 :             : void
     234                 :     6572113 : dead_debug_global_init (struct dead_debug_global *debug, bitmap used)
     235                 :             : {
     236                 :     6572113 :   debug->used = used;
     237                 :     6572113 :   debug->htab = NULL;
     238                 :     6572113 :   if (used)
     239                 :           0 :     bitmap_clear (used);
     240                 :     6572113 : }
     241                 :             : 
     242                 :             : /* Initialize DEBUG to an empty list, and clear USED, if given.  Link
     243                 :             :    back to GLOBAL, if given, and bring in used bits from it.  */
     244                 :             : 
     245                 :             : void
     246                 :   314088181 : dead_debug_local_init (struct dead_debug_local *debug, bitmap used,
     247                 :             :                        struct dead_debug_global *global)
     248                 :             : {
     249                 :   314088181 :   if (!used && global && global->used)
     250                 :     2636670 :     used = BITMAP_ALLOC (NULL);
     251                 :             : 
     252                 :   314088181 :   debug->head = NULL;
     253                 :   314088181 :   debug->global = global;
     254                 :   314088181 :   debug->used = used;
     255                 :   314088181 :   debug->to_rescan = NULL;
     256                 :             : 
     257                 :   314088181 :   if (used)
     258                 :             :     {
     259                 :     2636670 :       if (global && global->used)
     260                 :     2636670 :         bitmap_copy (used, global->used);
     261                 :             :       else
     262                 :           0 :         bitmap_clear (used);
     263                 :             :     }
     264                 :   314088181 : }
     265                 :             : 
     266                 :             : /* Locate the entry for REG in GLOBAL->htab.  */
     267                 :             : 
     268                 :             : static dead_debug_global_entry *
     269                 :     1247590 : dead_debug_global_find (struct dead_debug_global *global, rtx reg)
     270                 :             : {
     271                 :     1247590 :   dead_debug_global_entry temp_entry;
     272                 :     1247590 :   temp_entry.reg = reg;
     273                 :             : 
     274                 :     1247590 :   dead_debug_global_entry *entry = global->htab->find (&temp_entry);
     275                 :     1247590 :   gcc_checking_assert (entry && entry->reg == temp_entry.reg);
     276                 :             : 
     277                 :     1247590 :   return entry;
     278                 :             : }
     279                 :             : 
     280                 :             : /* Insert an entry mapping REG to DTEMP in GLOBAL->htab.  */
     281                 :             : 
     282                 :             : static dead_debug_global_entry *
     283                 :      125763 : dead_debug_global_insert (struct dead_debug_global *global, rtx reg, rtx dtemp)
     284                 :             : {
     285                 :      125763 :   dead_debug_global_entry temp_entry;
     286                 :      125763 :   temp_entry.reg = reg;
     287                 :      125763 :   temp_entry.dtemp = dtemp;
     288                 :             : 
     289                 :      125763 :   if (!global->htab)
     290                 :       67859 :     global->htab = new hash_table<dead_debug_hash_descr> (31);
     291                 :             : 
     292                 :      125763 :   dead_debug_global_entry **slot = global->htab->find_slot (&temp_entry,
     293                 :             :                                                             INSERT);
     294                 :      125763 :   gcc_checking_assert (!*slot);
     295                 :      125763 :   *slot = XNEW (dead_debug_global_entry);
     296                 :      125763 :   **slot = temp_entry;
     297                 :      125763 :   return *slot;
     298                 :             : }
     299                 :             : 
     300                 :             : /* If UREGNO, referenced by USE, is a pseudo marked as used in GLOBAL,
     301                 :             :    replace it with a USE of the debug temp recorded for it, and
     302                 :             :    return TRUE.  Otherwise, just return FALSE.
     303                 :             : 
     304                 :             :    If PTO_RESCAN is given, instead of rescanning modified INSNs right
     305                 :             :    away, add their UIDs to the bitmap, allocating one of *PTO_RESCAN
     306                 :             :    is NULL.  */
     307                 :             : 
     308                 :             : static bool
     309                 :     1297722 : dead_debug_global_replace_temp (struct dead_debug_global *global,
     310                 :             :                                 df_ref use, unsigned int uregno,
     311                 :             :                                 bitmap *pto_rescan)
     312                 :             : {
     313                 :     1297722 :   if (!global || uregno < FIRST_PSEUDO_REGISTER
     314                 :     1082289 :       || !global->used
     315                 :      882787 :       || !REG_P (*DF_REF_REAL_LOC (use))
     316                 :      882787 :       || REGNO (*DF_REF_REAL_LOC (use)) != uregno
     317                 :     2180509 :       || !bitmap_bit_p (global->used, uregno))
     318                 :      498471 :     return false;
     319                 :             : 
     320                 :      799251 :   dead_debug_global_entry *entry
     321                 :      799251 :     = dead_debug_global_find (global, *DF_REF_REAL_LOC (use));
     322                 :      799251 :   gcc_checking_assert (GET_CODE (entry->reg) == REG
     323                 :             :                        && REGNO (entry->reg) == uregno);
     324                 :             : 
     325                 :      799251 :   if (!entry->dtemp)
     326                 :             :     return true;
     327                 :             : 
     328                 :      799249 :   *DF_REF_REAL_LOC (use) = entry->dtemp;
     329                 :      799249 :   if (!pto_rescan)
     330                 :           0 :     df_insn_rescan (DF_REF_INSN (use));
     331                 :             :   else
     332                 :             :     {
     333                 :      799249 :       if (!*pto_rescan)
     334                 :           0 :         *pto_rescan = BITMAP_ALLOC (NULL);
     335                 :      799249 :       bitmap_set_bit (*pto_rescan, INSN_UID (DF_REF_INSN (use)));
     336                 :             :     }
     337                 :             : 
     338                 :             :   return true;
     339                 :             : }
     340                 :             : 
     341                 :             : /* Reset all debug uses in HEAD, and clear DEBUG->to_rescan bits of
     342                 :             :    each reset insn.  DEBUG is not otherwise modified.  If HEAD is
     343                 :             :    DEBUG->head, DEBUG->head will be set to NULL at the end.
     344                 :             :    Otherwise, entries from DEBUG->head that pertain to reset insns
     345                 :             :    will be removed, and only then rescanned.  */
     346                 :             : 
     347                 :             : static void
     348                 :   314093196 : dead_debug_reset_uses (struct dead_debug_local *debug,
     349                 :             :                        struct dead_debug_use *head)
     350                 :             : {
     351                 :   314093196 :   bool got_head = (debug->head == head);
     352                 :   314093196 :   bitmap rescan;
     353                 :   314093196 :   struct dead_debug_use **tailp = &debug->head;
     354                 :   314093196 :   struct dead_debug_use *cur;
     355                 :   314093196 :   bitmap_iterator bi;
     356                 :   314093196 :   unsigned int uid;
     357                 :             : 
     358                 :   314093196 :   if (got_head)
     359                 :   314093196 :     rescan = NULL;
     360                 :             :   else
     361                 :        1093 :     rescan = BITMAP_ALLOC (NULL);
     362                 :             : 
     363                 :   314200895 :   while (head)
     364                 :             :     {
     365                 :      107699 :       struct dead_debug_use *next = head->next;
     366                 :      107699 :       rtx_insn *insn;
     367                 :             : 
     368                 :      107699 :       insn = DF_REF_INSN (head->use);
     369                 :      107699 :       if (!next || DF_REF_INSN (next->use) != insn)
     370                 :             :         {
     371                 :      106409 :           INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     372                 :      106409 :           if (got_head)
     373                 :      105700 :             df_insn_rescan_debug_internal (insn);
     374                 :             :           else
     375                 :         709 :             bitmap_set_bit (rescan, INSN_UID (insn));
     376                 :      106409 :           if (debug->to_rescan)
     377                 :        1874 :             bitmap_clear_bit (debug->to_rescan, INSN_UID (insn));
     378                 :             :         }
     379                 :      107699 :       XDELETE (head);
     380                 :      107699 :       head = next;
     381                 :             :     }
     382                 :             : 
     383                 :   314093196 :   if (got_head)
     384                 :             :     {
     385                 :   314092103 :       debug->head = NULL;
     386                 :   314092103 :       return;
     387                 :             :     }
     388                 :             : 
     389                 :        1578 :   while ((cur = *tailp))
     390                 :         485 :     if (bitmap_bit_p (rescan, INSN_UID (DF_REF_INSN (cur->use))))
     391                 :             :       {
     392                 :           3 :         *tailp = cur->next;
     393                 :           3 :         XDELETE (cur);
     394                 :             :       }
     395                 :             :     else
     396                 :         482 :       tailp = &cur->next;
     397                 :             : 
     398                 :        1802 :   EXECUTE_IF_SET_IN_BITMAP (rescan, 0, uid, bi)
     399                 :             :     {
     400                 :        1418 :       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
     401                 :         709 :       if (insn_info)
     402                 :         709 :         df_insn_rescan_debug_internal (insn_info->insn);
     403                 :             :     }
     404                 :             : 
     405                 :        1093 :   BITMAP_FREE (rescan);
     406                 :             : }
     407                 :             : 
     408                 :             : /* Promote pending local uses of pseudos in DEBUG to global
     409                 :             :    substitutions.  Uses of non-pseudos are left alone for
     410                 :             :    resetting.  */
     411                 :             : 
     412                 :             : static void
     413                 :   123043615 : dead_debug_promote_uses (struct dead_debug_local *debug)
     414                 :             : {
     415                 :   123043615 :   for (struct dead_debug_use *head = debug->head, **headp = &debug->head;
     416                 :   123171169 :        head; head = *headp)
     417                 :             :     {
     418                 :      127554 :       rtx reg = *DF_REF_REAL_LOC (head->use);
     419                 :      127554 :       df_ref ref;
     420                 :      127554 :       dead_debug_global_entry *entry;
     421                 :             : 
     422                 :      129345 :       if (GET_CODE (reg) != REG
     423                 :      127554 :           || REGNO (reg) < FIRST_PSEUDO_REGISTER)
     424                 :             :         {
     425                 :        1791 :           headp = &head->next;
     426                 :        1791 :           continue;
     427                 :             :         }
     428                 :             : 
     429                 :      125763 :       if (!debug->global->used)
     430                 :       67859 :         debug->global->used = BITMAP_ALLOC (NULL);
     431                 :             : 
     432                 :      125763 :       bool added = bitmap_set_bit (debug->global->used, REGNO (reg));
     433                 :      125763 :       gcc_checking_assert (added);
     434                 :             : 
     435                 :      125763 :       entry = dead_debug_global_insert (debug->global, reg,
     436                 :             :                                         make_debug_expr_from_rtl (reg));
     437                 :             : 
     438                 :      125763 :       gcc_checking_assert (entry->dtemp);
     439                 :             : 
     440                 :             :       /* Tentatively remove the USE from the list.  */
     441                 :      125763 :       *headp = head->next;
     442                 :             : 
     443                 :      125763 :       if (!debug->to_rescan)
     444                 :      108293 :         debug->to_rescan = BITMAP_ALLOC (NULL);
     445                 :             : 
     446                 :     1591763 :       for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref;
     447                 :     1466000 :            ref = DF_REF_NEXT_REG (ref))
     448                 :     1466000 :         if (DEBUG_INSN_P (DF_REF_INSN (ref)))
     449                 :             :           {
     450                 :      799249 :             if (!dead_debug_global_replace_temp (debug->global, ref,
     451                 :             :                                                  REGNO (reg),
     452                 :             :                                                  &debug->to_rescan))
     453                 :             :               {
     454                 :           0 :                 rtx_insn *insn = DF_REF_INSN (ref);
     455                 :           0 :                 INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     456                 :           0 :                 bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
     457                 :             :               }
     458                 :             :           }
     459                 :             : 
     460                 :      362364 :       for (ref = DF_REG_DEF_CHAIN (REGNO (reg)); ref;
     461                 :      236601 :            ref = DF_REF_NEXT_REG (ref))
     462                 :      236601 :         if (!dead_debug_insert_temp (debug, REGNO (reg), DF_REF_INSN (ref),
     463                 :             :                                      DEBUG_TEMP_BEFORE_WITH_VALUE))
     464                 :             :           {
     465                 :        4335 :             rtx bind;
     466                 :        4335 :             bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
     467                 :        4335 :                                          DEBUG_EXPR_TREE_DECL (entry->dtemp),
     468                 :             :                                          gen_rtx_UNKNOWN_VAR_LOC (),
     469                 :             :                                          VAR_INIT_STATUS_INITIALIZED);
     470                 :        4335 :             rtx_insn *insn = emit_debug_insn_before (bind, DF_REF_INSN (ref));
     471                 :        4335 :             bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
     472                 :             :           }
     473                 :             : 
     474                 :      125763 :       entry->dtemp = NULL;
     475                 :      125763 :       XDELETE (head);
     476                 :             :     }
     477                 :   123043615 : }
     478                 :             : 
     479                 :             : /* Reset all debug insns with pending uses.  Release the bitmap in it,
     480                 :             :    unless it is USED.  USED must be the same bitmap passed to
     481                 :             :    dead_debug_local_init.  */
     482                 :             : 
     483                 :             : void
     484                 :   314088181 : dead_debug_local_finish (struct dead_debug_local *debug, bitmap used)
     485                 :             : {
     486                 :   314088181 :   if (debug->global)
     487                 :   123043615 :     dead_debug_promote_uses (debug);
     488                 :             : 
     489                 :   314088181 :   if (debug->used != used)
     490                 :     2894340 :     BITMAP_FREE (debug->used);
     491                 :             : 
     492                 :   314088181 :   dead_debug_reset_uses (debug, debug->head);
     493                 :             : 
     494                 :   314088181 :   if (debug->to_rescan)
     495                 :             :     {
     496                 :      215550 :       bitmap_iterator bi;
     497                 :      215550 :       unsigned int uid;
     498                 :             : 
     499                 :     1557105 :       EXECUTE_IF_SET_IN_BITMAP (debug->to_rescan, 0, uid, bi)
     500                 :             :         {
     501                 :     2683110 :           struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
     502                 :     1341555 :           if (insn_info)
     503                 :     1341555 :             df_insn_rescan (insn_info->insn);
     504                 :             :         }
     505                 :      215550 :       BITMAP_FREE (debug->to_rescan);
     506                 :             :     }
     507                 :   314088181 : }
     508                 :             : 
     509                 :             : /* Release GLOBAL->used unless it is the same as USED.  Release the
     510                 :             :    mapping hash table if it was initialized.  */
     511                 :             : 
     512                 :             : void
     513                 :     6572113 : dead_debug_global_finish (struct dead_debug_global *global, bitmap used)
     514                 :             : {
     515                 :     6572113 :   if (global->used != used)
     516                 :       67859 :     BITMAP_FREE (global->used);
     517                 :             : 
     518                 :     6572113 :   delete global->htab;
     519                 :     6572113 :   global->htab = NULL;
     520                 :     6572113 : }
     521                 :             : 
     522                 :             : /* Add USE to DEBUG, or substitute it right away if it's a pseudo in
     523                 :             :    the global substitution list.  USE must be a dead reference to
     524                 :             :    UREGNO in a debug insn.  Create a bitmap for DEBUG as needed.  */
     525                 :             : 
     526                 :             : void
     527                 :      498473 : dead_debug_add (struct dead_debug_local *debug, df_ref use, unsigned int uregno)
     528                 :             : {
     529                 :      498473 :   if (dead_debug_global_replace_temp (debug->global, use, uregno,
     530                 :             :                                       &debug->to_rescan))
     531                 :             :     return;
     532                 :             : 
     533                 :      498471 :   struct dead_debug_use *newddu = XNEW (struct dead_debug_use);
     534                 :             : 
     535                 :      498471 :   newddu->use = use;
     536                 :      498471 :   newddu->next = debug->head;
     537                 :      498471 :   debug->head = newddu;
     538                 :             : 
     539                 :      498471 :   if (!debug->used)
     540                 :      257670 :     debug->used = BITMAP_ALLOC (NULL);
     541                 :             : 
     542                 :             :   /* ??? If we dealt with split multi-registers below, we should set
     543                 :             :      all registers for the used mode in case of hardware
     544                 :             :      registers.  */
     545                 :      498471 :   bitmap_set_bit (debug->used, uregno);
     546                 :             : }
     547                 :             : 
     548                 :             : /* Like lowpart_subreg, but if a subreg is not valid for machine, force
     549                 :             :    it anyway - for use in debug insns.  */
     550                 :             : 
     551                 :             : static rtx
     552                 :        2449 : debug_lowpart_subreg (machine_mode outer_mode, rtx expr,
     553                 :             :                       machine_mode inner_mode)
     554                 :             : {
     555                 :        2449 :   if (inner_mode == VOIDmode)
     556                 :           0 :     inner_mode = GET_MODE (expr);
     557                 :        2449 :   poly_int64 offset = subreg_lowpart_offset (outer_mode, inner_mode);
     558                 :        2449 :   rtx ret = simplify_gen_subreg (outer_mode, expr, inner_mode, offset);
     559                 :        2449 :   if (ret)
     560                 :             :     return ret;
     561                 :           5 :   if (GET_MODE (expr) != VOIDmode)
     562                 :           3 :     return gen_rtx_raw_SUBREG (outer_mode, expr, offset);
     563                 :             :   return NULL_RTX;
     564                 :             : }
     565                 :             : 
     566                 :             : /* If UREGNO is referenced by any entry in DEBUG, emit a debug insn
     567                 :             :    before or after INSN (depending on WHERE), that binds a (possibly
     568                 :             :    global) debug temp to the widest-mode use of UREGNO, if WHERE is
     569                 :             :    *_WITH_REG, or the value stored in UREGNO by INSN otherwise, and
     570                 :             :    replace all uses of UREGNO in DEBUG with uses of the debug temp.
     571                 :             :    INSN must be where UREGNO dies, if WHERE is *_BEFORE_*, or where it
     572                 :             :    is set otherwise.  Return the number of debug insns emitted.  */
     573                 :             : 
     574                 :             : int
     575                 :   864653201 : dead_debug_insert_temp (struct dead_debug_local *debug, unsigned int uregno,
     576                 :             :                         rtx_insn *insn, enum debug_temp_where where)
     577                 :             : {
     578                 :   864653201 :   struct dead_debug_use **tailp = &debug->head;
     579                 :   864653201 :   struct dead_debug_use *cur;
     580                 :   864653201 :   struct dead_debug_use *uses = NULL;
     581                 :   864653201 :   struct dead_debug_use **usesp = &uses;
     582                 :   864653201 :   rtx reg = NULL_RTX;
     583                 :   864653201 :   rtx breg;
     584                 :   864653201 :   rtx dval = NULL_RTX;
     585                 :   864653201 :   rtx bind;
     586                 :   864653201 :   bool global;
     587                 :             : 
     588                 :   864653201 :   if (!debug->used)
     589                 :             :     return 0;
     590                 :             : 
     591                 :    75746151 :   global = (debug->global && debug->global->used
     592                 :   149098534 :             && bitmap_bit_p (debug->global->used, uregno));
     593                 :             : 
     594                 :    75667509 :   if (!global && !bitmap_clear_bit (debug->used, uregno))
     595                 :             :     return 0;
     596                 :             : 
     597                 :             :   /* Move all uses of uregno from debug->head to uses, setting mode to
     598                 :             :      the widest referenced mode.  */
     599                 :     1082961 :   while ((cur = *tailp))
     600                 :             :     {
     601                 :      458912 :       if (DF_REF_REGNO (cur->use) == uregno)
     602                 :             :         {
     603                 :             :           /* If this loc has been changed e.g. to debug_expr already
     604                 :             :              as part of a multi-register use, just drop it.  */
     605                 :      265715 :           if (!REG_P (*DF_REF_REAL_LOC (cur->use)))
     606                 :             :             {
     607                 :       41540 :               *tailp = cur->next;
     608                 :       41540 :               XDELETE (cur);
     609                 :       41540 :               continue;
     610                 :             :             }
     611                 :      224175 :           *usesp = cur;
     612                 :      224175 :           usesp = &cur->next;
     613                 :      224175 :           *tailp = cur->next;
     614                 :      224175 :           cur->next = NULL;
     615                 :             :           /* "may" rather than "must" because we want (for example)
     616                 :             :              N V4SFs to win over plain V4SF even though N might be 1.  */
     617                 :      224175 :           rtx candidate = *DF_REF_REAL_LOC (cur->use);
     618                 :      224175 :           if (!reg
     619                 :      272646 :               || maybe_lt (GET_MODE_BITSIZE (GET_MODE (reg)),
     620                 :       96942 :                            GET_MODE_BITSIZE (GET_MODE (candidate))))
     621                 :             :             reg = candidate;
     622                 :             :         }
     623                 :             :       else
     624                 :      193197 :         tailp = &(*tailp)->next;
     625                 :             :     }
     626                 :             : 
     627                 :             :   /* We may have dangling bits in debug->used for registers that were part
     628                 :             :      of a multi-register use, one component of which has been reset.  */
     629                 :      624049 :   if (reg == NULL)
     630                 :             :     {
     631                 :      448345 :       gcc_checking_assert (!uses);
     632                 :      448345 :       if (!global)
     633                 :             :         return 0;
     634                 :             :     }
     635                 :             : 
     636                 :      175704 :   if (global)
     637                 :             :     {
     638                 :      448339 :       if (!reg)
     639                 :      448339 :         reg = regno_reg_rtx[uregno];
     640                 :      448339 :       dead_debug_global_entry *entry
     641                 :      448339 :         = dead_debug_global_find (debug->global, reg);
     642                 :      448339 :       gcc_checking_assert (entry->reg == reg);
     643                 :      448339 :       dval = entry->dtemp;
     644                 :      448339 :       if (!dval)
     645                 :             :         return 0;
     646                 :             :     }
     647                 :             : 
     648                 :      412305 :   gcc_checking_assert (uses || global);
     649                 :             : 
     650                 :      412305 :   breg = reg;
     651                 :             :   /* Recover the expression INSN stores in REG.  */
     652                 :      412305 :   if (where == DEBUG_TEMP_BEFORE_WITH_VALUE)
     653                 :             :     {
     654                 :      260696 :       rtx set = single_set (insn);
     655                 :      260696 :       rtx dest, src;
     656                 :             : 
     657                 :      260696 :       if (set)
     658                 :             :         {
     659                 :      257211 :           dest = SET_DEST (set);
     660                 :      257211 :           src = SET_SRC (set);
     661                 :             :           /* Reset uses if the REG-setting insn is a CALL.  Asm in
     662                 :             :              DEBUG_INSN is never useful, we can't emit debug info for
     663                 :             :              that.  And for volatile_insn_p, it is actually harmful -
     664                 :             :              DEBUG_INSNs shouldn't have any side-effects.  */
     665                 :      257210 :           if (GET_CODE (src) == CALL || GET_CODE (src) == ASM_OPERANDS
     666                 :      514417 :               || volatile_insn_p (src))
     667                 :             :             set = NULL_RTX;
     668                 :             :         }
     669                 :             : 
     670                 :             :       /* ??? Should we try to extract it from a PARALLEL?  */
     671                 :      260696 :       if (!set)
     672                 :             :         breg = NULL;
     673                 :             :       /* Cool, it's the same REG, we can use SRC.  */
     674                 :      257206 :       else if (dest == reg)
     675                 :      253331 :         breg = cleanup_auto_inc_dec (src, VOIDmode);
     676                 :        3875 :       else if (REG_P (dest))
     677                 :             :         {
     678                 :             :           /* Hmm...  Something's fishy, we should be setting REG here.  */
     679                 :        1965 :           if (REGNO (dest) != REGNO (reg))
     680                 :             :             breg = NULL;
     681                 :             :           /* If we're not overwriting all the hardware registers that
     682                 :             :              setting REG in its mode would, we won't know what to bind
     683                 :             :              the debug temp to.  ??? We could bind the debug_expr to a
     684                 :             :              CONCAT or PARALLEL with the split multi-registers, and
     685                 :             :              replace them as we found the corresponding sets.  */
     686                 :        1374 :           else if (REG_NREGS (reg) != REG_NREGS (dest))
     687                 :             :             breg = NULL;
     688                 :             :           /* Ok, it's the same (hardware) REG, but with a different
     689                 :             :              mode, so SUBREG it.  */
     690                 :             :           else
     691                 :        1322 :             breg = debug_lowpart_subreg (GET_MODE (reg),
     692                 :             :                                          cleanup_auto_inc_dec (src, VOIDmode),
     693                 :        1322 :                                          GET_MODE (dest));
     694                 :             :         }
     695                 :        1910 :       else if (GET_CODE (dest) == SUBREG)
     696                 :             :         {
     697                 :             :           /* We should be setting REG here.  Lose.  */
     698                 :        1910 :           if (REGNO (SUBREG_REG (dest)) != REGNO (reg))
     699                 :             :             breg = NULL;
     700                 :             :           /* Lose if we're setting something other than the lowpart of
     701                 :             :              REG.  */
     702                 :        1910 :           else if (!subreg_lowpart_p (dest))
     703                 :             :             breg = NULL;
     704                 :             :           /* If we're not overwriting all the hardware registers that
     705                 :             :              setting REG in its mode would, we won't know what to bind
     706                 :             :              the debug temp to.  */
     707                 :        1030 :           else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
     708                 :        1030 :                    && (REG_NREGS (reg)
     709                 :           0 :                        != hard_regno_nregs (REGNO (reg), GET_MODE (dest))))
     710                 :             :             breg = NULL;
     711                 :             :           /* Yay, we can use SRC, just adjust its mode.  */
     712                 :             :           else
     713                 :        1030 :             breg = debug_lowpart_subreg (GET_MODE (reg),
     714                 :             :                                          cleanup_auto_inc_dec (src, VOIDmode),
     715                 :        1030 :                                          GET_MODE (dest));
     716                 :             :         }
     717                 :             :       /* Oh well, we're out of luck.  */
     718                 :             :       else
     719                 :             :         breg = NULL;
     720                 :             : 
     721                 :             :       /* We couldn't figure out the value stored in REG, so reset all
     722                 :             :          of its pending debug uses.  */
     723                 :      255683 :       if (!breg)
     724                 :             :         {
     725                 :        5015 :           dead_debug_reset_uses (debug, uses);
     726                 :        5015 :           return 0;
     727                 :             :         }
     728                 :             :     }
     729                 :             : 
     730                 :             :   /* If there's a single (debug) use of an otherwise unused REG, and
     731                 :             :      the debug use is not part of a larger expression, then it
     732                 :             :      probably doesn't make sense to introduce a new debug temp.  */
     733                 :      407290 :   if (where == DEBUG_TEMP_AFTER_WITH_REG && !uses->next)
     734                 :             :     {
     735                 :       42713 :       rtx_insn *next = DF_REF_INSN (uses->use);
     736                 :             : 
     737                 :       42713 :       if (DEBUG_INSN_P (next) && reg == INSN_VAR_LOCATION_LOC (next))
     738                 :             :         {
     739                 :       39747 :           XDELETE (uses);
     740                 :       39747 :           return 0;
     741                 :             :         }
     742                 :             :     }
     743                 :             : 
     744                 :      367543 :   if (!global)
     745                 :             :     /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
     746                 :      135277 :     dval = make_debug_expr_from_rtl (reg);
     747                 :             : 
     748                 :             :   /* Emit a debug bind insn before the insn in which reg dies.  */
     749                 :      367543 :   bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
     750                 :             :                                DEBUG_EXPR_TREE_DECL (dval), breg,
     751                 :             :                                VAR_INIT_STATUS_INITIALIZED);
     752                 :             : 
     753                 :      367543 :   if (where == DEBUG_TEMP_AFTER_WITH_REG
     754                 :      367543 :       || where == DEBUG_TEMP_AFTER_WITH_REG_FORCE)
     755                 :       95493 :     bind = emit_debug_insn_after (bind, insn);
     756                 :             :   else
     757                 :      272050 :     bind = emit_debug_insn_before (bind, insn);
     758                 :      367543 :   if (debug->to_rescan == NULL)
     759                 :      107257 :     debug->to_rescan = BITMAP_ALLOC (NULL);
     760                 :      367543 :   bitmap_set_bit (debug->to_rescan, INSN_UID (bind));
     761                 :             : 
     762                 :             :   /* Adjust all uses.  */
     763                 :      918805 :   while ((cur = uses))
     764                 :             :     {
     765                 :      183719 :       if (GET_MODE (*DF_REF_REAL_LOC (cur->use)) == GET_MODE (reg))
     766                 :      183622 :         *DF_REF_REAL_LOC (cur->use) = dval;
     767                 :             :       else
     768                 :          97 :         *DF_REF_REAL_LOC (cur->use)
     769                 :          97 :           = debug_lowpart_subreg (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval,
     770                 :          97 :                                   GET_MODE (dval));
     771                 :             :       /* ??? Should we simplify subreg of subreg?  */
     772                 :      183719 :       bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use)));
     773                 :      183719 :       uses = cur->next;
     774                 :      183719 :       XDELETE (cur);
     775                 :             :     }
     776                 :             : 
     777                 :             :   return 1;
     778                 :             : }
        

Generated by: LCOV version 2.0-1

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