LCOV - code coverage report
Current view: top level - gcc - valtrack.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 323 349 92.6 %
Date: 2020-04-04 11:58:09 Functions: 15 16 93.8 %
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-2020 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                 :          0 : gen_lowpart_for_debug (machine_mode mode, rtx x)
      40                 :            : {
      41                 :          0 :   rtx result = gen_lowpart_if_possible (mode, x);
      42                 :          0 :   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                 :     570468 : cleanup_auto_inc_dec (rtx src, machine_mode mem_mode ATTRIBUTE_UNUSED)
      57                 :            : {
      58                 :     570468 :   rtx x = src;
      59                 :            : 
      60                 :     570468 :   const RTX_CODE code = GET_CODE (x);
      61                 :     570468 :   int i;
      62                 :     570468 :   const char *fmt;
      63                 :            : 
      64                 :     570468 :   switch (code)
      65                 :            :     {
      66                 :            :     case REG:
      67                 :            :     CASE_CONST_ANY:
      68                 :            :     case SYMBOL_REF:
      69                 :            :     case CODE_LABEL:
      70                 :            :     case PC:
      71                 :            :     case CC0:
      72                 :            :     case SCRATCH:
      73                 :            :       /* SCRATCH must be shared because they represent distinct values.  */
      74                 :            :       return x;
      75                 :          0 :     case CLOBBER:
      76                 :            :       /* Share clobbers of hard registers (like cc0), but do not share pseudo reg
      77                 :            :          clobbers or clobbers of hard registers that originated as pseudos.
      78                 :            :          This is needed to allow safe register renaming.  */
      79                 :          0 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
      80                 :          0 :           && ORIGINAL_REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 0)))
      81                 :            :         return x;
      82                 :            :       break;
      83                 :            : 
      84                 :        845 :     case CONST:
      85                 :        845 :       if (shared_const_p (x))
      86                 :            :         return x;
      87                 :            :       break;
      88                 :            : 
      89                 :      54158 :     case MEM:
      90                 :      54158 :       mem_mode = GET_MODE (x);
      91                 :      54158 :       break;
      92                 :            : 
      93                 :          0 :     case PRE_INC:
      94                 :          0 :     case PRE_DEC:
      95                 :          0 :       {
      96                 :          0 :         gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode);
      97                 :          0 :         poly_int64 offset = GET_MODE_SIZE (mem_mode);
      98                 :          0 :         if (code == PRE_DEC)
      99                 :          0 :           offset = -offset;
     100                 :          0 :         return gen_rtx_PLUS (GET_MODE (x),
     101                 :            :                              cleanup_auto_inc_dec (XEXP (x, 0), mem_mode),
     102                 :            :                              gen_int_mode (offset, GET_MODE (x)));
     103                 :            :       }
     104                 :            : 
     105                 :          1 :     case POST_INC:
     106                 :          1 :     case POST_DEC:
     107                 :          1 :     case PRE_MODIFY:
     108                 :          1 :     case POST_MODIFY:
     109                 :          1 :       return cleanup_auto_inc_dec (code == PRE_MODIFY
     110                 :            :                                    ? XEXP (x, 1) : XEXP (x, 0),
     111                 :          1 :                                    mem_mode);
     112                 :            : 
     113                 :            :     default:
     114                 :            :       break;
     115                 :            :     }
     116                 :            : 
     117                 :            :   /* Copy the various flags, fields, and other information.  We assume
     118                 :            :      that all fields need copying, and then clear the fields that should
     119                 :            :      not be copied.  That is the sensible default behavior, and forces
     120                 :            :      us to explicitly document why we are *not* copying a flag.  */
     121                 :     179735 :   x = shallow_copy_rtx (x);
     122                 :            : 
     123                 :            :   /* We do not copy FRAME_RELATED for INSNs.  */
     124                 :     179735 :   if (INSN_P (x))
     125                 :          0 :     RTX_FLAG (x, frame_related) = 0;
     126                 :            : 
     127                 :     179735 :   fmt = GET_RTX_FORMAT (code);
     128                 :     537401 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     129                 :     357666 :     if (fmt[i] == 'e')
     130                 :     297516 :       XEXP (x, i) = cleanup_auto_inc_dec (XEXP (x, i), mem_mode);
     131                 :      60150 :     else if (fmt[i] == 'E' || fmt[i] == 'V')
     132                 :            :       {
     133                 :        268 :         int j;
     134                 :        268 :         XVEC (x, i) = rtvec_alloc (XVECLEN (x, i));
     135                 :        548 :         for (j = 0; j < XVECLEN (x, i); j++)
     136                 :        280 :           XVECEXP (x, i, j)
     137                 :        280 :             = cleanup_auto_inc_dec (XVECEXP (src, i, j), mem_mode);
     138                 :            :       }
     139                 :            : 
     140                 :            :   return x;
     141                 :            : }
     142                 :            : 
     143                 :            : /* Auxiliary data structure for propagate_for_debug_stmt.  */
     144                 :            : 
     145                 :            : struct rtx_subst_pair
     146                 :            : {
     147                 :            :   rtx to;
     148                 :            :   bool adjusted;
     149                 :            :   rtx_insn *insn;
     150                 :            : };
     151                 :            : 
     152                 :            : /* DATA points to an rtx_subst_pair.  Return the value that should be
     153                 :            :    substituted.  */
     154                 :            : 
     155                 :            : static rtx
     156                 :    3508390 : propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data)
     157                 :            : {
     158                 :    3508390 :   struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
     159                 :            : 
     160                 :    3508390 :   if (!rtx_equal_p (from, old_rtx))
     161                 :            :     return NULL_RTX;
     162                 :     162004 :   if (!pair->adjusted)
     163                 :            :     {
     164                 :     132704 :       pair->adjusted = true;
     165                 :     132704 :       pair->to = cleanup_auto_inc_dec (pair->to, VOIDmode);
     166                 :     132704 :       pair->to = make_compound_operation (pair->to, SET);
     167                 :            :       /* Avoid propagation from growing DEBUG_INSN expressions too much.  */
     168                 :     132704 :       int cnt = 0;
     169                 :     265408 :       subrtx_iterator::array_type array;
     170                 :     401350 :       FOR_EACH_SUBRTX (iter, array, pair->to, ALL)
     171                 :     286456 :         if (REG_P (*iter) && ++cnt > 1)
     172                 :            :           {
     173                 :      17810 :             rtx dval = make_debug_expr_from_rtl (old_rtx);
     174                 :      17810 :             rtx to = pair->to;
     175                 :      17810 :             if (volatile_insn_p (to))
     176                 :          0 :               to = gen_rtx_UNKNOWN_VAR_LOC ();
     177                 :            :             /* Emit a debug bind insn.  */
     178                 :      17810 :             rtx bind
     179                 :      17810 :               = gen_rtx_VAR_LOCATION (GET_MODE (old_rtx),
     180                 :            :                                       DEBUG_EXPR_TREE_DECL (dval), to,
     181                 :            :                                       VAR_INIT_STATUS_INITIALIZED);
     182                 :      17810 :             rtx_insn *bind_insn = emit_debug_insn_before (bind, pair->insn);
     183                 :      17810 :             df_insn_rescan (bind_insn);
     184                 :      17810 :             pair->to = dval;
     185                 :      17810 :             break;
     186                 :            :           }
     187                 :     132704 :       return pair->to;
     188                 :            :     }
     189                 :      29300 :   return copy_rtx (pair->to);
     190                 :            : }
     191                 :            : 
     192                 :            : /* Replace all the occurrences of DEST with SRC in DEBUG_INSNs between INSN
     193                 :            :    and LAST, not including INSN, but including LAST.  Also stop at the end
     194                 :            :    of THIS_BASIC_BLOCK.  */
     195                 :            : 
     196                 :            : void
     197                 :    1277330 : propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src,
     198                 :            :                      basic_block this_basic_block)
     199                 :            : {
     200                 :    1277330 :   rtx_insn *next, *end = NEXT_INSN (BB_END (this_basic_block));
     201                 :    1277330 :   rtx loc;
     202                 :    1277330 :   rtx (*saved_rtl_hook_no_emit) (machine_mode, rtx);
     203                 :            : 
     204                 :    1277330 :   struct rtx_subst_pair p;
     205                 :    1277330 :   p.to = src;
     206                 :    1277330 :   p.adjusted = false;
     207                 :    1277330 :   p.insn = NEXT_INSN (insn);
     208                 :            : 
     209                 :    1277330 :   next = NEXT_INSN (insn);
     210                 :    1277330 :   last = NEXT_INSN (last);
     211                 :    1277330 :   saved_rtl_hook_no_emit = rtl_hooks.gen_lowpart_no_emit;
     212                 :    1277330 :   rtl_hooks.gen_lowpart_no_emit = gen_lowpart_for_debug;
     213                 :    6265640 :   while (next != last && next != end)
     214                 :            :     {
     215                 :    4988310 :       insn = next;
     216                 :    4988310 :       next = NEXT_INSN (insn);
     217                 :    4988310 :       if (DEBUG_BIND_INSN_P (insn))
     218                 :            :         {
     219                 :    1965900 :           loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn),
     220                 :            :                                          dest, propagate_for_debug_subst, &p);
     221                 :    1965900 :           if (loc == INSN_VAR_LOCATION_LOC (insn))
     222                 :    1804220 :             continue;
     223                 :     161676 :           if (volatile_insn_p (loc))
     224                 :          0 :             loc = gen_rtx_UNKNOWN_VAR_LOC ();
     225                 :     161676 :           INSN_VAR_LOCATION_LOC (insn) = loc;
     226                 :     161676 :           df_insn_rescan (insn);
     227                 :            :         }
     228                 :            :     }
     229                 :    1277330 :   rtl_hooks.gen_lowpart_no_emit = saved_rtl_hook_no_emit;
     230                 :    1277330 : }
     231                 :            : 
     232                 :            : /* Initialize DEBUG to an empty list, and clear USED, if given.  */
     233                 :            : 
     234                 :            : void
     235                 :    4693130 : dead_debug_global_init (struct dead_debug_global *debug, bitmap used)
     236                 :            : {
     237                 :    4693130 :   debug->used = used;
     238                 :    4693130 :   debug->htab = NULL;
     239                 :    4693130 :   if (used)
     240                 :          0 :     bitmap_clear (used);
     241                 :    4693130 : }
     242                 :            : 
     243                 :            : /* Initialize DEBUG to an empty list, and clear USED, if given.  Link
     244                 :            :    back to GLOBAL, if given, and bring in used bits from it.  */
     245                 :            : 
     246                 :            : void
     247                 :  232906000 : dead_debug_local_init (struct dead_debug_local *debug, bitmap used,
     248                 :            :                        struct dead_debug_global *global)
     249                 :            : {
     250                 :  232906000 :   if (!used && global && global->used)
     251                 :    1325750 :     used = BITMAP_ALLOC (NULL);
     252                 :            : 
     253                 :  232906000 :   debug->head = NULL;
     254                 :  232906000 :   debug->global = global;
     255                 :  232906000 :   debug->used = used;
     256                 :  232906000 :   debug->to_rescan = NULL;
     257                 :            : 
     258                 :  232906000 :   if (used)
     259                 :            :     {
     260                 :    1325750 :       if (global && global->used)
     261                 :    1325750 :         bitmap_copy (used, global->used);
     262                 :            :       else
     263                 :          0 :         bitmap_clear (used);
     264                 :            :     }
     265                 :  232906000 : }
     266                 :            : 
     267                 :            : /* Locate the entry for REG in GLOBAL->htab.  */
     268                 :            : 
     269                 :            : static dead_debug_global_entry *
     270                 :     703675 : dead_debug_global_find (struct dead_debug_global *global, rtx reg)
     271                 :            : {
     272                 :     703675 :   dead_debug_global_entry temp_entry;
     273                 :     703675 :   temp_entry.reg = reg;
     274                 :            : 
     275                 :     703675 :   dead_debug_global_entry *entry = global->htab->find (&temp_entry);
     276                 :     703675 :   gcc_checking_assert (entry && entry->reg == temp_entry.reg);
     277                 :            : 
     278                 :     703675 :   return entry;
     279                 :            : }
     280                 :            : 
     281                 :            : /* Insert an entry mapping REG to DTEMP in GLOBAL->htab.  */
     282                 :            : 
     283                 :            : static dead_debug_global_entry *
     284                 :      73412 : dead_debug_global_insert (struct dead_debug_global *global, rtx reg, rtx dtemp)
     285                 :            : {
     286                 :      73412 :   dead_debug_global_entry temp_entry;
     287                 :      73412 :   temp_entry.reg = reg;
     288                 :      73412 :   temp_entry.dtemp = dtemp;
     289                 :            : 
     290                 :      73412 :   if (!global->htab)
     291                 :      40944 :     global->htab = new hash_table<dead_debug_hash_descr> (31);
     292                 :            : 
     293                 :      73412 :   dead_debug_global_entry **slot = global->htab->find_slot (&temp_entry,
     294                 :            :                                                             INSERT);
     295                 :      73412 :   gcc_checking_assert (!*slot);
     296                 :      73412 :   *slot = XNEW (dead_debug_global_entry);
     297                 :      73412 :   **slot = temp_entry;
     298                 :      73412 :   return *slot;
     299                 :            : }
     300                 :            : 
     301                 :            : /* If UREGNO, referenced by USE, is a pseudo marked as used in GLOBAL,
     302                 :            :    replace it with a USE of the debug temp recorded for it, and
     303                 :            :    return TRUE.  Otherwise, just return FALSE.
     304                 :            : 
     305                 :            :    If PTO_RESCAN is given, instead of rescanning modified INSNs right
     306                 :            :    away, add their UIDs to the bitmap, allocating one of *PTO_RESCAN
     307                 :            :    is NULL.  */
     308                 :            : 
     309                 :            : static bool
     310                 :     747331 : dead_debug_global_replace_temp (struct dead_debug_global *global,
     311                 :            :                                 df_ref use, unsigned int uregno,
     312                 :            :                                 bitmap *pto_rescan)
     313                 :            : {
     314                 :     747331 :   if (!global || uregno < FIRST_PSEUDO_REGISTER
     315                 :     649095 :       || !global->used
     316                 :     526489 :       || !REG_P (*DF_REF_REAL_LOC (use))
     317                 :     526479 :       || REGNO (*DF_REF_REAL_LOC (use)) != uregno
     318                 :    1273810 :       || !bitmap_bit_p (global->used, uregno))
     319                 :     275615 :     return false;
     320                 :            : 
     321                 :     471716 :   dead_debug_global_entry *entry
     322                 :     471716 :     = dead_debug_global_find (global, *DF_REF_REAL_LOC (use));
     323                 :     471716 :   gcc_checking_assert (GET_CODE (entry->reg) == REG
     324                 :            :                        && REGNO (entry->reg) == uregno);
     325                 :            : 
     326                 :     471716 :   if (!entry->dtemp)
     327                 :            :     return true;
     328                 :            : 
     329                 :     471716 :   *DF_REF_REAL_LOC (use) = entry->dtemp;
     330                 :     471716 :   if (!pto_rescan)
     331                 :          0 :     df_insn_rescan (DF_REF_INSN (use));
     332                 :            :   else
     333                 :            :     {
     334                 :     471716 :       if (!*pto_rescan)
     335                 :          0 :         *pto_rescan = BITMAP_ALLOC (NULL);
     336                 :     471716 :       bitmap_set_bit (*pto_rescan, INSN_UID (DF_REF_INSN (use)));
     337                 :            :     }
     338                 :            : 
     339                 :            :   return true;
     340                 :            : }
     341                 :            : 
     342                 :            : /* Reset all debug uses in HEAD, and clear DEBUG->to_rescan bits of
     343                 :            :    each reset insn.  DEBUG is not otherwise modified.  If HEAD is
     344                 :            :    DEBUG->head, DEBUG->head will be set to NULL at the end.
     345                 :            :    Otherwise, entries from DEBUG->head that pertain to reset insns
     346                 :            :    will be removed, and only then rescanned.  */
     347                 :            : 
     348                 :            : static void
     349                 :  232908000 : dead_debug_reset_uses (struct dead_debug_local *debug,
     350                 :            :                        struct dead_debug_use *head)
     351                 :            : {
     352                 :  232908000 :   bool got_head = (debug->head == head);
     353                 :  232908000 :   bitmap rescan;
     354                 :  232908000 :   struct dead_debug_use **tailp = &debug->head;
     355                 :  232908000 :   struct dead_debug_use *cur;
     356                 :  232908000 :   bitmap_iterator bi;
     357                 :  232908000 :   unsigned int uid;
     358                 :            : 
     359                 :  232908000 :   if (got_head)
     360                 :  232908000 :     rescan = NULL;
     361                 :            :   else
     362                 :        399 :     rescan = BITMAP_ALLOC (NULL);
     363                 :            : 
     364                 :  232932000 :   while (head)
     365                 :            :     {
     366                 :      23258 :       struct dead_debug_use *next = head->next;
     367                 :      23258 :       rtx_insn *insn;
     368                 :            : 
     369                 :      23258 :       insn = DF_REF_INSN (head->use);
     370                 :      23258 :       if (!next || DF_REF_INSN (next->use) != insn)
     371                 :            :         {
     372                 :      23042 :           INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     373                 :      23042 :           if (got_head)
     374                 :      22861 :             df_insn_rescan_debug_internal (insn);
     375                 :            :           else
     376                 :        181 :             bitmap_set_bit (rescan, INSN_UID (insn));
     377                 :      23042 :           if (debug->to_rescan)
     378                 :        721 :             bitmap_clear_bit (debug->to_rescan, INSN_UID (insn));
     379                 :            :         }
     380                 :      23258 :       XDELETE (head);
     381                 :      23258 :       head = next;
     382                 :            :     }
     383                 :            : 
     384                 :  232908000 :   if (got_head)
     385                 :            :     {
     386                 :  232908000 :       debug->head = NULL;
     387                 :  232908000 :       return;
     388                 :            :     }
     389                 :            : 
     390                 :        743 :   while ((cur = *tailp))
     391                 :        344 :     if (bitmap_bit_p (rescan, INSN_UID (DF_REF_INSN (cur->use))))
     392                 :            :       {
     393                 :          2 :         *tailp = cur->next;
     394                 :          2 :         XDELETE (cur);
     395                 :            :       }
     396                 :            :     else
     397                 :        342 :       tailp = &cur->next;
     398                 :            : 
     399                 :        580 :   EXECUTE_IF_SET_IN_BITMAP (rescan, 0, uid, bi)
     400                 :            :     {
     401                 :        362 :       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
     402                 :        181 :       if (insn_info)
     403                 :        181 :         df_insn_rescan_debug_internal (insn_info->insn);
     404                 :            :     }
     405                 :            : 
     406                 :        399 :   BITMAP_FREE (rescan);
     407                 :            : }
     408                 :            : 
     409                 :            : /* Promote pending local uses of pseudos in DEBUG to global
     410                 :            :    substitutions.  Uses of non-pseudos are left alone for
     411                 :            :    resetting.  */
     412                 :            : 
     413                 :            : static void
     414                 :   84045600 : dead_debug_promote_uses (struct dead_debug_local *debug)
     415                 :            : {
     416                 :   84045600 :   for (struct dead_debug_use *head = debug->head, **headp = &debug->head;
     417                 :   84120000 :        head; head = *headp)
     418                 :            :     {
     419                 :      74398 :       rtx reg = *DF_REF_REAL_LOC (head->use);
     420                 :      74398 :       df_ref ref;
     421                 :      74398 :       dead_debug_global_entry *entry;
     422                 :            : 
     423                 :      75384 :       if (GET_CODE (reg) != REG
     424                 :      74398 :           || REGNO (reg) < FIRST_PSEUDO_REGISTER)
     425                 :            :         {
     426                 :        986 :           headp = &head->next;
     427                 :        986 :           continue;
     428                 :            :         }
     429                 :            : 
     430                 :      73412 :       if (!debug->global->used)
     431                 :      40944 :         debug->global->used = BITMAP_ALLOC (NULL);
     432                 :            : 
     433                 :      73412 :       bool added = bitmap_set_bit (debug->global->used, REGNO (reg));
     434                 :      73412 :       gcc_checking_assert (added);
     435                 :            : 
     436                 :      73412 :       entry = dead_debug_global_insert (debug->global, reg,
     437                 :            :                                         make_debug_expr_from_rtl (reg));
     438                 :            : 
     439                 :      73412 :       gcc_checking_assert (entry->dtemp);
     440                 :            : 
     441                 :            :       /* Tentatively remove the USE from the list.  */
     442                 :      73412 :       *headp = head->next;
     443                 :            : 
     444                 :      73412 :       if (!debug->to_rescan)
     445                 :      61787 :         debug->to_rescan = BITMAP_ALLOC (NULL);
     446                 :            : 
     447                 :     911625 :       for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref;
     448                 :     838213 :            ref = DF_REF_NEXT_REG (ref))
     449                 :     838213 :         if (DEBUG_INSN_P (DF_REF_INSN (ref)))
     450                 :            :           {
     451                 :     471726 :             if (!dead_debug_global_replace_temp (debug->global, ref,
     452                 :            :                                                  REGNO (reg),
     453                 :            :                                                  &debug->to_rescan))
     454                 :            :               {
     455                 :         10 :                 rtx_insn *insn = DF_REF_INSN (ref);
     456                 :         10 :                 INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     457                 :         10 :                 bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
     458                 :            :               }
     459                 :            :           }
     460                 :            : 
     461                 :     198229 :       for (ref = DF_REG_DEF_CHAIN (REGNO (reg)); ref;
     462                 :     124817 :            ref = DF_REF_NEXT_REG (ref))
     463                 :     124817 :         if (!dead_debug_insert_temp (debug, REGNO (reg), DF_REF_INSN (ref),
     464                 :            :                                      DEBUG_TEMP_BEFORE_WITH_VALUE))
     465                 :            :           {
     466                 :       2294 :             rtx bind;
     467                 :       2294 :             bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
     468                 :       2294 :                                          DEBUG_EXPR_TREE_DECL (entry->dtemp),
     469                 :            :                                          gen_rtx_UNKNOWN_VAR_LOC (),
     470                 :            :                                          VAR_INIT_STATUS_INITIALIZED);
     471                 :       2294 :             rtx_insn *insn = emit_debug_insn_before (bind, DF_REF_INSN (ref));
     472                 :       2294 :             bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
     473                 :            :           }
     474                 :            : 
     475                 :      73412 :       entry->dtemp = NULL;
     476                 :      73412 :       XDELETE (head);
     477                 :            :     }
     478                 :   84045600 : }
     479                 :            : 
     480                 :            : /* Reset all debug insns with pending uses.  Release the bitmap in it,
     481                 :            :    unless it is USED.  USED must be the same bitmap passed to
     482                 :            :    dead_debug_local_init.  */
     483                 :            : 
     484                 :            : void
     485                 :  232906000 : dead_debug_local_finish (struct dead_debug_local *debug, bitmap used)
     486                 :            : {
     487                 :  232906000 :   if (debug->global)
     488                 :   84045600 :     dead_debug_promote_uses (debug);
     489                 :            : 
     490                 :  232906000 :   if (debug->used != used)
     491                 :    1463610 :     BITMAP_FREE (debug->used);
     492                 :            : 
     493                 :  232906000 :   dead_debug_reset_uses (debug, debug->head);
     494                 :            : 
     495                 :  232906000 :   if (debug->to_rescan)
     496                 :            :     {
     497                 :     125638 :       bitmap_iterator bi;
     498                 :     125638 :       unsigned int uid;
     499                 :            : 
     500                 :     915585 :       EXECUTE_IF_SET_IN_BITMAP (debug->to_rescan, 0, uid, bi)
     501                 :            :         {
     502                 :    1579890 :           struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
     503                 :     789947 :           if (insn_info)
     504                 :     789947 :             df_insn_rescan (insn_info->insn);
     505                 :            :         }
     506                 :     125638 :       BITMAP_FREE (debug->to_rescan);
     507                 :            :     }
     508                 :  232906000 : }
     509                 :            : 
     510                 :            : /* Release GLOBAL->used unless it is the same as USED.  Release the
     511                 :            :    mapping hash table if it was initialized.  */
     512                 :            : 
     513                 :            : void
     514                 :    4693130 : dead_debug_global_finish (struct dead_debug_global *global, bitmap used)
     515                 :            : {
     516                 :    4693130 :   if (global->used != used)
     517                 :      40944 :     BITMAP_FREE (global->used);
     518                 :            : 
     519                 :    4693130 :   delete global->htab;
     520                 :    4693130 :   global->htab = NULL;
     521                 :    4693130 : }
     522                 :            : 
     523                 :            : /* Add USE to DEBUG, or substitute it right away if it's a pseudo in
     524                 :            :    the global substitution list.  USE must be a dead reference to
     525                 :            :    UREGNO in a debug insn.  Create a bitmap for DEBUG as needed.  */
     526                 :            : 
     527                 :            : void
     528                 :     275605 : dead_debug_add (struct dead_debug_local *debug, df_ref use, unsigned int uregno)
     529                 :            : {
     530                 :     275605 :   if (dead_debug_global_replace_temp (debug->global, use, uregno,
     531                 :            :                                       &debug->to_rescan))
     532                 :            :     return;
     533                 :            : 
     534                 :     275605 :   struct dead_debug_use *newddu = XNEW (struct dead_debug_use);
     535                 :            : 
     536                 :     275605 :   newddu->use = use;
     537                 :     275605 :   newddu->next = debug->head;
     538                 :     275605 :   debug->head = newddu;
     539                 :            : 
     540                 :     275605 :   if (!debug->used)
     541                 :     137865 :     debug->used = BITMAP_ALLOC (NULL);
     542                 :            : 
     543                 :            :   /* ??? If we dealt with split multi-registers below, we should set
     544                 :            :      all registers for the used mode in case of hardware
     545                 :            :      registers.  */
     546                 :     275605 :   bitmap_set_bit (debug->used, uregno);
     547                 :            : }
     548                 :            : 
     549                 :            : /* Like lowpart_subreg, but if a subreg is not valid for machine, force
     550                 :            :    it anyway - for use in debug insns.  */
     551                 :            : 
     552                 :            : static rtx
     553                 :        979 : debug_lowpart_subreg (machine_mode outer_mode, rtx expr,
     554                 :            :                       machine_mode inner_mode)
     555                 :            : {
     556                 :        979 :   if (inner_mode == VOIDmode)
     557                 :          0 :     inner_mode = GET_MODE (expr);
     558                 :        979 :   poly_int64 offset = subreg_lowpart_offset (outer_mode, inner_mode);
     559                 :        979 :   rtx ret = simplify_gen_subreg (outer_mode, expr, inner_mode, offset);
     560                 :        979 :   if (ret)
     561                 :            :     return ret;
     562                 :          0 :   return gen_rtx_raw_SUBREG (outer_mode, expr, offset);
     563                 :            : }
     564                 :            : 
     565                 :            : /* If UREGNO is referenced by any entry in DEBUG, emit a debug insn
     566                 :            :    before or after INSN (depending on WHERE), that binds a (possibly
     567                 :            :    global) debug temp to the widest-mode use of UREGNO, if WHERE is
     568                 :            :    *_WITH_REG, or the value stored in UREGNO by INSN otherwise, and
     569                 :            :    replace all uses of UREGNO in DEBUG with uses of the debug temp.
     570                 :            :    INSN must be where UREGNO dies, if WHERE is *_BEFORE_*, or where it
     571                 :            :    is set otherwise.  Return the number of debug insns emitted.  */
     572                 :            : 
     573                 :            : int
     574                 :  639113000 : dead_debug_insert_temp (struct dead_debug_local *debug, unsigned int uregno,
     575                 :            :                         rtx_insn *insn, enum debug_temp_where where)
     576                 :            : {
     577                 :  639113000 :   struct dead_debug_use **tailp = &debug->head;
     578                 :  639113000 :   struct dead_debug_use *cur;
     579                 :  639113000 :   struct dead_debug_use *uses = NULL;
     580                 :  639113000 :   struct dead_debug_use **usesp = &uses;
     581                 :  639113000 :   rtx reg = NULL_RTX;
     582                 :  639113000 :   rtx breg;
     583                 :  639113000 :   rtx dval = NULL_RTX;
     584                 :  639113000 :   rtx bind;
     585                 :  639113000 :   bool global;
     586                 :            : 
     587                 :  639113000 :   if (!debug->used)
     588                 :            :     return 0;
     589                 :            : 
     590                 :   35919400 :   global = (debug->global && debug->global->used
     591                 :   70415700 :             && bitmap_bit_p (debug->global->used, uregno));
     592                 :            : 
     593                 :   35834900 :   if (!global && !bitmap_clear_bit (debug->used, uregno))
     594                 :            :     return 0;
     595                 :            : 
     596                 :            :   /* Move all uses of uregno from debug->head to uses, setting mode to
     597                 :            :      the widest referenced mode.  */
     598                 :     653764 :   while ((cur = *tailp))
     599                 :            :     {
     600                 :     312308 :       if (DF_REF_REGNO (cur->use) == uregno)
     601                 :            :         {
     602                 :            :           /* If this loc has been changed e.g. to debug_expr already
     603                 :            :              as part of a multi-register use, just drop it.  */
     604                 :     179114 :           if (!REG_P (*DF_REF_REAL_LOC (cur->use)))
     605                 :            :             {
     606                 :      37021 :               *tailp = cur->next;
     607                 :      37021 :               XDELETE (cur);
     608                 :      37021 :               continue;
     609                 :            :             }
     610                 :     142093 :           *usesp = cur;
     611                 :     142093 :           usesp = &cur->next;
     612                 :     142093 :           *tailp = cur->next;
     613                 :     142093 :           cur->next = NULL;
     614                 :            :           /* "may" rather than "must" because we want (for example)
     615                 :            :              N V4SFs to win over plain V4SF even though N might be 1.  */
     616                 :     142093 :           rtx candidate = *DF_REF_REAL_LOC (cur->use);
     617                 :     142093 :           if (!reg
     618                 :     174773 :               || maybe_lt (GET_MODE_BITSIZE (GET_MODE (reg)),
     619                 :      65360 :                            GET_MODE_BITSIZE (GET_MODE (candidate))))
     620                 :            :             reg = candidate;
     621                 :            :         }
     622                 :            :       else
     623                 :     133194 :         tailp = &(*tailp)->next;
     624                 :            :     }
     625                 :            : 
     626                 :            :   /* We may have dangling bits in debug->used for registers that were part
     627                 :            :      of a multi-register use, one component of which has been reset.  */
     628                 :     341456 :   if (reg == NULL)
     629                 :            :     {
     630                 :     232043 :       gcc_checking_assert (!uses);
     631                 :     232043 :       if (!global)
     632                 :            :         return 0;
     633                 :            :     }
     634                 :            : 
     635                 :     341372 :   if (global)
     636                 :            :     {
     637                 :     231959 :       if (!reg)
     638                 :     231959 :         reg = regno_reg_rtx[uregno];
     639                 :     231959 :       dead_debug_global_entry *entry
     640                 :     231959 :         = dead_debug_global_find (debug->global, reg);
     641                 :     231959 :       gcc_checking_assert (entry->reg == reg);
     642                 :     231959 :       dval = entry->dtemp;
     643                 :     231959 :       if (!dval)
     644                 :            :         return 0;
     645                 :            :     }
     646                 :            : 
     647                 :     234230 :   gcc_checking_assert (uses || global);
     648                 :            : 
     649                 :     234230 :   breg = reg;
     650                 :            :   /* Recover the expression INSN stores in REG.  */
     651                 :     234230 :   if (where == DEBUG_TEMP_BEFORE_WITH_VALUE)
     652                 :            :     {
     653                 :     142394 :       rtx set = single_set (insn);
     654                 :     142394 :       rtx dest, src;
     655                 :            : 
     656                 :     142394 :       if (set)
     657                 :            :         {
     658                 :     140493 :           dest = SET_DEST (set);
     659                 :     140493 :           src = SET_SRC (set);
     660                 :            :           /* Reset uses if the REG-setting insn is a CALL.  Asm in
     661                 :            :              DEBUG_INSN is never useful, we can't emit debug info for
     662                 :            :              that.  And for volatile_insn_p, it is actually harmful -
     663                 :            :              DEBUG_INSNs shouldn't have any side-effects.  */
     664                 :     140491 :           if (GET_CODE (src) == CALL || GET_CODE (src) == ASM_OPERANDS
     665                 :     280977 :               || volatile_insn_p (src))
     666                 :            :             set = NULL_RTX;
     667                 :            :         }
     668                 :            : 
     669                 :            :       /* ??? Should we try to extract it from a PARALLEL?  */
     670                 :     142394 :       if (!set)
     671                 :            :         breg = NULL;
     672                 :            :       /* Cool, it's the same REG, we can use SRC.  */
     673                 :     140484 :       else if (dest == reg)
     674                 :     139009 :         breg = cleanup_auto_inc_dec (src, VOIDmode);
     675                 :       1475 :       else if (REG_P (dest))
     676                 :            :         {
     677                 :            :           /* Hmm...  Something's fishy, we should be setting REG here.  */
     678                 :        530 :           if (REGNO (dest) != REGNO (reg))
     679                 :            :             breg = NULL;
     680                 :            :           /* If we're not overwriting all the hardware registers that
     681                 :            :              setting REG in its mode would, we won't know what to bind
     682                 :            :              the debug temp to.  ??? We could bind the debug_expr to a
     683                 :            :              CONCAT or PARALLEL with the split multi-registers, and
     684                 :            :              replace them as we found the corresponding sets.  */
     685                 :        487 :           else if (REG_NREGS (reg) != REG_NREGS (dest))
     686                 :            :             breg = NULL;
     687                 :            :           /* Ok, it's the same (hardware) REG, but with a different
     688                 :            :              mode, so SUBREG it.  */
     689                 :            :           else
     690                 :        442 :             breg = debug_lowpart_subreg (GET_MODE (reg),
     691                 :            :                                          cleanup_auto_inc_dec (src, VOIDmode),
     692                 :        442 :                                          GET_MODE (dest));
     693                 :            :         }
     694                 :        945 :       else if (GET_CODE (dest) == SUBREG)
     695                 :            :         {
     696                 :            :           /* We should be setting REG here.  Lose.  */
     697                 :        945 :           if (REGNO (SUBREG_REG (dest)) != REGNO (reg))
     698                 :            :             breg = NULL;
     699                 :            :           /* Lose if we're setting something other than the lowpart of
     700                 :            :              REG.  */
     701                 :        945 :           else if (!subreg_lowpart_p (dest))
     702                 :            :             breg = NULL;
     703                 :            :           /* If we're not overwriting all the hardware registers that
     704                 :            :              setting REG in its mode would, we won't know what to bind
     705                 :            :              the debug temp to.  */
     706                 :        516 :           else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
     707                 :        516 :                    && (REG_NREGS (reg)
     708                 :          0 :                        != hard_regno_nregs (REGNO (reg), GET_MODE (dest))))
     709                 :            :             breg = NULL;
     710                 :            :           /* Yay, we can use SRC, just adjust its mode.  */
     711                 :            :           else
     712                 :        516 :             breg = debug_lowpart_subreg (GET_MODE (reg),
     713                 :            :                                          cleanup_auto_inc_dec (src, VOIDmode),
     714                 :        516 :                                          GET_MODE (dest));
     715                 :            :         }
     716                 :            :       /* Oh well, we're out of luck.  */
     717                 :            :       else
     718                 :            :         breg = NULL;
     719                 :            : 
     720                 :            :       /* We couldn't figure out the value stored in REG, so reset all
     721                 :            :          of its pending debug uses.  */
     722                 :     139967 :       if (!breg)
     723                 :            :         {
     724                 :       2427 :           dead_debug_reset_uses (debug, uses);
     725                 :       2427 :           return 0;
     726                 :            :         }
     727                 :            :     }
     728                 :            : 
     729                 :            :   /* If there's a single (debug) use of an otherwise unused REG, and
     730                 :            :      the debug use is not part of a larger expression, then it
     731                 :            :      probably doesn't make sense to introduce a new debug temp.  */
     732                 :     231803 :   if (where == DEBUG_TEMP_AFTER_WITH_REG && !uses->next)
     733                 :            :     {
     734                 :      27829 :       rtx_insn *next = DF_REF_INSN (uses->use);
     735                 :            : 
     736                 :      27829 :       if (DEBUG_INSN_P (next) && reg == INSN_VAR_LOCATION_LOC (next))
     737                 :            :         {
     738                 :      25290 :           XDELETE (uses);
     739                 :      25290 :           return 0;
     740                 :            :         }
     741                 :            :     }
     742                 :            : 
     743                 :     206513 :   if (!global)
     744                 :            :     /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
     745                 :      83990 :     dval = make_debug_expr_from_rtl (reg);
     746                 :            : 
     747                 :            :   /* Emit a debug bind insn before the insn in which reg dies.  */
     748                 :     206513 :   bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
     749                 :            :                                DEBUG_EXPR_TREE_DECL (dval), breg,
     750                 :            :                                VAR_INIT_STATUS_INITIALIZED);
     751                 :            : 
     752                 :     206513 :   if (where == DEBUG_TEMP_AFTER_WITH_REG
     753                 :     206513 :       || where == DEBUG_TEMP_AFTER_WITH_REG_FORCE)
     754                 :      56347 :     bind = emit_debug_insn_after (bind, insn);
     755                 :            :   else
     756                 :     150166 :     bind = emit_debug_insn_before (bind, insn);
     757                 :     206513 :   if (debug->to_rescan == NULL)
     758                 :      63851 :     debug->to_rescan = BITMAP_ALLOC (NULL);
     759                 :     206513 :   bitmap_set_bit (debug->to_rescan, INSN_UID (bind));
     760                 :            : 
     761                 :            :   /* Adjust all uses.  */
     762                 :     323135 :   while ((cur = uses))
     763                 :            :     {
     764                 :     116622 :       if (GET_MODE (*DF_REF_REAL_LOC (cur->use)) == GET_MODE (reg))
     765                 :     116601 :         *DF_REF_REAL_LOC (cur->use) = dval;
     766                 :            :       else
     767                 :         21 :         *DF_REF_REAL_LOC (cur->use)
     768                 :         21 :           = debug_lowpart_subreg (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval,
     769                 :         21 :                                   GET_MODE (dval));
     770                 :            :       /* ??? Should we simplify subreg of subreg?  */
     771                 :     116622 :       bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use)));
     772                 :     116622 :       uses = cur->next;
     773                 :     116622 :       XDELETE (cur);
     774                 :            :     }
     775                 :            : 
     776                 :            :   return 1;
     777                 :            : }

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.