LCOV - code coverage report
Current view: top level - gcc - tree-object-size.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 552 651 84.8 %
Date: 2020-04-04 11:58:09 Functions: 20 22 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* __builtin_object_size (ptr, object_size_type) computation
       2                 :            :    Copyright (C) 2004-2020 Free Software Foundation, Inc.
       3                 :            :    Contributed by Jakub Jelinek <jakub@redhat.com>
       4                 :            : 
       5                 :            : This file is part of GCC.
       6                 :            : 
       7                 :            : GCC is free software; you can redistribute it and/or modify
       8                 :            : it under the terms of the GNU General Public License as published by
       9                 :            : the Free Software Foundation; either version 3, or (at your option)
      10                 :            : any later version.
      11                 :            : 
      12                 :            : GCC is distributed in the hope that it will be useful,
      13                 :            : but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            : GNU General Public License for more details.
      16                 :            : 
      17                 :            : You should have received a copy of the GNU General Public License
      18                 :            : along with GCC; see the file COPYING3.  If not see
      19                 :            : <http://www.gnu.org/licenses/>.  */
      20                 :            : 
      21                 :            : #include "config.h"
      22                 :            : #include "system.h"
      23                 :            : #include "coretypes.h"
      24                 :            : #include "backend.h"
      25                 :            : #include "tree.h"
      26                 :            : #include "gimple.h"
      27                 :            : #include "tree-pass.h"
      28                 :            : #include "ssa.h"
      29                 :            : #include "gimple-pretty-print.h"
      30                 :            : #include "fold-const.h"
      31                 :            : #include "tree-object-size.h"
      32                 :            : #include "gimple-fold.h"
      33                 :            : #include "gimple-iterator.h"
      34                 :            : #include "tree-cfg.h"
      35                 :            : #include "stringpool.h"
      36                 :            : #include "attribs.h"
      37                 :            : 
      38                 :            : struct object_size_info
      39                 :            : {
      40                 :            :   int object_size_type;
      41                 :            :   unsigned char pass;
      42                 :            :   bool changed;
      43                 :            :   bitmap visited, reexamine;
      44                 :            :   unsigned int *depths;
      45                 :            :   unsigned int *stack, *tos;
      46                 :            : };
      47                 :            : 
      48                 :            : static const unsigned HOST_WIDE_INT unknown[4] = {
      49                 :            :   HOST_WIDE_INT_M1U,
      50                 :            :   HOST_WIDE_INT_M1U,
      51                 :            :   0,
      52                 :            :   0
      53                 :            : };
      54                 :            : 
      55                 :            : static tree compute_object_offset (const_tree, const_tree);
      56                 :            : static bool addr_object_size (struct object_size_info *,
      57                 :            :                               const_tree, int, unsigned HOST_WIDE_INT *,
      58                 :            :                               tree * = NULL, tree * = NULL);
      59                 :            : static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
      60                 :            : static tree pass_through_call (const gcall *);
      61                 :            : static void collect_object_sizes_for (struct object_size_info *, tree);
      62                 :            : static void expr_object_size (struct object_size_info *, tree, tree);
      63                 :            : static bool merge_object_sizes (struct object_size_info *, tree, tree,
      64                 :            :                                 unsigned HOST_WIDE_INT);
      65                 :            : static bool plus_stmt_object_size (struct object_size_info *, tree, gimple *);
      66                 :            : static bool cond_expr_object_size (struct object_size_info *, tree, gimple *);
      67                 :            : static void init_offset_limit (void);
      68                 :            : static void check_for_plus_in_loops (struct object_size_info *, tree);
      69                 :            : static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
      70                 :            :                                        unsigned int);
      71                 :            : 
      72                 :            : /* object_sizes[0] is upper bound for number of bytes till the end of
      73                 :            :    the object.
      74                 :            :    object_sizes[1] is upper bound for number of bytes till the end of
      75                 :            :    the subobject (innermost array or field with address taken).
      76                 :            :    object_sizes[2] is lower bound for number of bytes till the end of
      77                 :            :    the object and object_sizes[3] lower bound for subobject.  */
      78                 :            : static vec<unsigned HOST_WIDE_INT> object_sizes[4];
      79                 :            : 
      80                 :            : /* Bitmaps what object sizes have been computed already.  */
      81                 :            : static bitmap computed[4];
      82                 :            : 
      83                 :            : /* Maximum value of offset we consider to be addition.  */
      84                 :            : static unsigned HOST_WIDE_INT offset_limit;
      85                 :            : 
      86                 :            : 
      87                 :            : /* Initialize OFFSET_LIMIT variable.  */
      88                 :            : static void
      89                 :      34319 : init_offset_limit (void)
      90                 :            : {
      91                 :      34319 :   if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)))
      92                 :      34319 :     offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype));
      93                 :            :   else
      94                 :          0 :     offset_limit = -1;
      95                 :      34319 :   offset_limit /= 2;
      96                 :      34319 : }
      97                 :            : 
      98                 :            : 
      99                 :            : /* Compute offset of EXPR within VAR.  Return error_mark_node
     100                 :            :    if unknown.  */
     101                 :            : 
     102                 :            : static tree
     103                 :      67284 : compute_object_offset (const_tree expr, const_tree var)
     104                 :            : {
     105                 :      67284 :   enum tree_code code = PLUS_EXPR;
     106                 :      67284 :   tree base, off, t;
     107                 :            : 
     108                 :      67284 :   if (expr == var)
     109                 :      30639 :     return size_zero_node;
     110                 :            : 
     111                 :      36645 :   switch (TREE_CODE (expr))
     112                 :            :     {
     113                 :      15800 :     case COMPONENT_REF:
     114                 :      15800 :       base = compute_object_offset (TREE_OPERAND (expr, 0), var);
     115                 :      15800 :       if (base == error_mark_node)
     116                 :            :         return base;
     117                 :            : 
     118                 :      15800 :       t = TREE_OPERAND (expr, 1);
     119                 :      15800 :       off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
     120                 :            :                         size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
     121                 :            :                                   / BITS_PER_UNIT));
     122                 :      15800 :       break;
     123                 :            : 
     124                 :          4 :     case REALPART_EXPR:
     125                 :          4 :     CASE_CONVERT:
     126                 :          4 :     case VIEW_CONVERT_EXPR:
     127                 :          4 :     case NON_LVALUE_EXPR:
     128                 :          4 :       return compute_object_offset (TREE_OPERAND (expr, 0), var);
     129                 :            : 
     130                 :          4 :     case IMAGPART_EXPR:
     131                 :          4 :       base = compute_object_offset (TREE_OPERAND (expr, 0), var);
     132                 :          4 :       if (base == error_mark_node)
     133                 :            :         return base;
     134                 :            : 
     135                 :          4 :       off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
     136                 :          4 :       break;
     137                 :            : 
     138                 :      20837 :     case ARRAY_REF:
     139                 :      20837 :       base = compute_object_offset (TREE_OPERAND (expr, 0), var);
     140                 :      20837 :       if (base == error_mark_node)
     141                 :            :         return base;
     142                 :            : 
     143                 :      20837 :       t = TREE_OPERAND (expr, 1);
     144                 :      20837 :       tree low_bound, unit_size;
     145                 :      20837 :       low_bound = array_ref_low_bound (CONST_CAST_TREE (expr));
     146                 :      20837 :       unit_size = array_ref_element_size (CONST_CAST_TREE (expr));
     147                 :      20837 :       if (! integer_zerop (low_bound))
     148                 :      13167 :         t = fold_build2 (MINUS_EXPR, TREE_TYPE (t), t, low_bound);
     149                 :      20837 :       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
     150                 :            :         {
     151                 :         12 :           code = MINUS_EXPR;
     152                 :         12 :           t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
     153                 :            :         }
     154                 :      20837 :       t = fold_convert (sizetype, t);
     155                 :      20837 :       off = size_binop (MULT_EXPR, unit_size, t);
     156                 :      20837 :       break;
     157                 :            : 
     158                 :          0 :     case MEM_REF:
     159                 :          0 :       gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
     160                 :          0 :       return wide_int_to_tree (sizetype, mem_ref_offset (expr));
     161                 :            : 
     162                 :          0 :     default:
     163                 :          0 :       return error_mark_node;
     164                 :            :     }
     165                 :            : 
     166                 :      36641 :   return size_binop (code, base, off);
     167                 :            : }
     168                 :            : 
     169                 :            : 
     170                 :            : /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
     171                 :            :    OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
     172                 :            :    If unknown, return unknown[object_size_type].  */
     173                 :            : 
     174                 :            : static bool
     175                 :     268391 : addr_object_size (struct object_size_info *osi, const_tree ptr,
     176                 :            :                   int object_size_type, unsigned HOST_WIDE_INT *psize,
     177                 :            :                   tree *pdecl /* = NULL */, tree *poff /* = NULL */)
     178                 :            : {
     179                 :     268391 :   tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
     180                 :            : 
     181                 :     268391 :   tree dummy_decl, dummy_off = size_zero_node;
     182                 :     268391 :   if (!pdecl)
     183                 :       5826 :     pdecl = &dummy_decl;
     184                 :     268391 :   if (!poff)
     185                 :       5826 :     poff = &dummy_off;
     186                 :            : 
     187                 :     268391 :   gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
     188                 :            : 
     189                 :            :   /* Set to unknown and overwrite just before returning if the size
     190                 :            :      could be determined.  */
     191                 :     268391 :   *psize = unknown[object_size_type];
     192                 :            : 
     193                 :     268391 :   pt_var = TREE_OPERAND (ptr, 0);
     194                 :     313058 :   while (handled_component_p (pt_var))
     195                 :      44667 :     pt_var = TREE_OPERAND (pt_var, 0);
     196                 :            : 
     197                 :     268391 :   if (pt_var
     198                 :     268391 :       && TREE_CODE (pt_var) == MEM_REF)
     199                 :            :     {
     200                 :      17551 :       unsigned HOST_WIDE_INT sz;
     201                 :            : 
     202                 :       2538 :       if (!osi || (object_size_type & 1) != 0
     203                 :      18362 :           || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
     204                 :            :         {
     205                 :      16751 :           compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
     206                 :            :                                        object_size_type & ~1, &sz, pdecl, poff);
     207                 :            :         }
     208                 :            :       else
     209                 :            :         {
     210                 :        800 :           tree var = TREE_OPERAND (pt_var, 0);
     211                 :        800 :           if (osi->pass == 0)
     212                 :        800 :             collect_object_sizes_for (osi, var);
     213                 :       1600 :           if (bitmap_bit_p (computed[object_size_type],
     214                 :        800 :                             SSA_NAME_VERSION (var)))
     215                 :        800 :             sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
     216                 :            :           else
     217                 :          0 :             sz = unknown[object_size_type];
     218                 :            :         }
     219                 :      17551 :       if (sz != unknown[object_size_type])
     220                 :            :         {
     221                 :      11234 :           offset_int mem_offset;
     222                 :      11234 :           if (mem_ref_offset (pt_var).is_constant (&mem_offset))
     223                 :            :             {
     224                 :      11234 :               offset_int dsz = wi::sub (sz, mem_offset);
     225                 :      11234 :               if (wi::neg_p (dsz))
     226                 :         24 :                 sz = 0;
     227                 :      11210 :               else if (wi::fits_uhwi_p (dsz))
     228                 :      11210 :                 sz = dsz.to_uhwi ();
     229                 :            :               else
     230                 :          0 :                 sz = unknown[object_size_type];
     231                 :            :             }
     232                 :            :           else
     233                 :            :             sz = unknown[object_size_type];
     234                 :            :         }
     235                 :            : 
     236                 :      17551 :       if (sz != unknown[object_size_type] && sz < offset_limit)
     237                 :      17551 :         pt_var_size = size_int (sz);
     238                 :            :     }
     239                 :     250840 :   else if (pt_var
     240                 :     250840 :            && DECL_P (pt_var)
     241                 :     188357 :            && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
     242                 :     187303 :            && tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
     243                 :            :     {
     244                 :     187303 :       *pdecl = pt_var;
     245                 :     187303 :       pt_var_size = DECL_SIZE_UNIT (pt_var);
     246                 :            :     }
     247                 :      63537 :   else if (pt_var
     248                 :      63537 :            && TREE_CODE (pt_var) == STRING_CST
     249                 :      62483 :            && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
     250                 :      62483 :            && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
     251                 :      62483 :            && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
     252                 :      62483 :               < offset_limit)
     253                 :     267337 :     pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
     254                 :            :   else
     255                 :            :     return false;
     256                 :            : 
     257                 :     267337 :   if (pt_var != TREE_OPERAND (ptr, 0))
     258                 :            :     {
     259                 :      35437 :       tree var;
     260                 :            : 
     261                 :      35437 :       if (object_size_type & 1)
     262                 :            :         {
     263                 :       2579 :           var = TREE_OPERAND (ptr, 0);
     264                 :            : 
     265                 :       2579 :           while (var != pt_var
     266                 :       2579 :                  && TREE_CODE (var) != BIT_FIELD_REF
     267                 :       2579 :                  && TREE_CODE (var) != COMPONENT_REF
     268                 :       1545 :                  && TREE_CODE (var) != ARRAY_REF
     269                 :         16 :                  && TREE_CODE (var) != ARRAY_RANGE_REF
     270                 :         16 :                  && TREE_CODE (var) != REALPART_EXPR
     271                 :       2587 :                  && TREE_CODE (var) != IMAGPART_EXPR)
     272                 :          0 :             var = TREE_OPERAND (var, 0);
     273                 :       2579 :           if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
     274                 :       1529 :             var = TREE_OPERAND (var, 0);
     275                 :       2579 :           if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
     276                 :       2571 :               || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
     277                 :       5141 :               || (pt_var_size
     278                 :       1534 :                   && tree_int_cst_lt (pt_var_size,
     279                 :       1534 :                                       TYPE_SIZE_UNIT (TREE_TYPE (var)))))
     280                 :            :             var = pt_var;
     281                 :       2492 :           else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
     282                 :            :             {
     283                 :            :               tree v = var;
     284                 :            :               /* For &X->fld, compute object size only if fld isn't the last
     285                 :            :                  field, as struct { int i; char c[1]; } is often used instead
     286                 :            :                  of flexible array member.  */
     287                 :       3310 :               while (v && v != pt_var)
     288                 :       1655 :                 switch (TREE_CODE (v))
     289                 :            :                   {
     290                 :          0 :                   case ARRAY_REF:
     291                 :          0 :                     if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
     292                 :          0 :                         && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
     293                 :            :                       {
     294                 :          0 :                         tree domain
     295                 :          0 :                           = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
     296                 :          0 :                         if (domain
     297                 :          0 :                             && TYPE_MAX_VALUE (domain)
     298                 :          0 :                             && TREE_CODE (TYPE_MAX_VALUE (domain))
     299                 :            :                                == INTEGER_CST
     300                 :          0 :                             && tree_int_cst_lt (TREE_OPERAND (v, 1),
     301                 :          0 :                                                 TYPE_MAX_VALUE (domain)))
     302                 :            :                           {
     303                 :            :                             v = NULL_TREE;
     304                 :            :                             break;
     305                 :            :                           }
     306                 :            :                       }
     307                 :          0 :                     v = TREE_OPERAND (v, 0);
     308                 :          0 :                     break;
     309                 :            :                   case REALPART_EXPR:
     310                 :            :                   case IMAGPART_EXPR:
     311                 :            :                     v = NULL_TREE;
     312                 :            :                     break;
     313                 :       1655 :                   case COMPONENT_REF:
     314                 :       1655 :                     if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
     315                 :            :                       {
     316                 :            :                         v = NULL_TREE;
     317                 :            :                         break;
     318                 :            :                       }
     319                 :       1698 :                     while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
     320                 :       1576 :                       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
     321                 :            :                           != UNION_TYPE
     322                 :       1576 :                           && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
     323                 :            :                           != QUAL_UNION_TYPE)
     324                 :            :                         break;
     325                 :            :                       else
     326                 :        522 :                         v = TREE_OPERAND (v, 0);
     327                 :       1176 :                     if (TREE_CODE (v) == COMPONENT_REF
     328                 :       1176 :                         && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
     329                 :            :                            == RECORD_TYPE)
     330                 :            :                       {
     331                 :       1054 :                         tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
     332                 :       1454 :                         for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
     333                 :        875 :                           if (TREE_CODE (fld_chain) == FIELD_DECL)
     334                 :            :                             break;
     335                 :            : 
     336                 :       1054 :                         if (fld_chain)
     337                 :            :                           {
     338                 :            :                             v = NULL_TREE;
     339                 :            :                             break;
     340                 :            :                           }
     341                 :        579 :                         v = TREE_OPERAND (v, 0);
     342                 :            :                       }
     343                 :        857 :                     while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
     344                 :        234 :                       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
     345                 :            :                           != UNION_TYPE
     346                 :        234 :                           && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
     347                 :            :                           != QUAL_UNION_TYPE)
     348                 :            :                         break;
     349                 :            :                       else
     350                 :        156 :                         v = TREE_OPERAND (v, 0);
     351                 :        701 :                     if (v != pt_var)
     352                 :            :                       v = NULL_TREE;
     353                 :            :                     else
     354                 :        529 :                       v = pt_var;
     355                 :            :                     break;
     356                 :            :                   default:
     357                 :       3310 :                     v = pt_var;
     358                 :            :                     break;
     359                 :            :                   }
     360                 :       1655 :               if (v == pt_var)
     361                 :        529 :                 var = pt_var;
     362                 :            :             }
     363                 :            :         }
     364                 :            :       else
     365                 :            :         var = pt_var;
     366                 :            : 
     367                 :      35437 :       if (var != pt_var)
     368                 :       1614 :         var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
     369                 :      33823 :       else if (!pt_var_size)
     370                 :            :         return false;
     371                 :            :       else
     372                 :            :         var_size = pt_var_size;
     373                 :      30209 :       bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
     374                 :      30209 :       if (bytes != error_mark_node)
     375                 :            :         {
     376                 :      30209 :           if (TREE_CODE (bytes) == INTEGER_CST
     377                 :      30209 :               && tree_int_cst_lt (var_size, bytes))
     378                 :         46 :             bytes = size_zero_node;
     379                 :            :           else
     380                 :      30163 :             bytes = size_binop (MINUS_EXPR, var_size, bytes);
     381                 :      30209 :           *poff = bytes;
     382                 :            :         }
     383                 :      30209 :       if (var != pt_var
     384                 :      30209 :           && pt_var_size
     385                 :        918 :           && TREE_CODE (pt_var) == MEM_REF
     386                 :        430 :           && bytes != error_mark_node)
     387                 :            :         {
     388                 :        430 :           tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
     389                 :        430 :           if (bytes2 != error_mark_node)
     390                 :            :             {
     391                 :        430 :               if (TREE_CODE (bytes2) == INTEGER_CST
     392                 :        430 :                   && tree_int_cst_lt (pt_var_size, bytes2))
     393                 :          9 :                 bytes2 = size_zero_node;
     394                 :            :               else
     395                 :        421 :                 bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
     396                 :        430 :               *poff = size_binop (PLUS_EXPR, *poff, bytes2);
     397                 :        430 :               bytes = size_binop (MIN_EXPR, bytes, bytes2);
     398                 :            :             }
     399                 :            :         }
     400                 :            :     }
     401                 :     231900 :   else if (!pt_var_size)
     402                 :            :     return false;
     403                 :            :   else
     404                 :            :     bytes = pt_var_size;
     405                 :            : 
     406                 :     261706 :   if (tree_fits_uhwi_p (bytes))
     407                 :            :     {
     408                 :     261706 :       *psize = tree_to_uhwi (bytes);
     409                 :     261706 :       return true;
     410                 :            :     }
     411                 :            : 
     412                 :            :   return false;
     413                 :            : }
     414                 :            : 
     415                 :            : 
     416                 :            : /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
     417                 :            :    Handles calls to functions declared with attribute alloc_size.
     418                 :            :    OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
     419                 :            :    If unknown, return unknown[object_size_type].  */
     420                 :            : 
     421                 :            : static unsigned HOST_WIDE_INT
     422                 :       1479 : alloc_object_size (const gcall *call, int object_size_type)
     423                 :            : {
     424                 :       1479 :   gcc_assert (is_gimple_call (call));
     425                 :            : 
     426                 :       1479 :   tree calltype;
     427                 :       1479 :   if (tree callfn = gimple_call_fndecl (call))
     428                 :       1413 :     calltype = TREE_TYPE (callfn);
     429                 :            :   else
     430                 :         66 :     calltype = gimple_call_fntype (call);
     431                 :            : 
     432                 :       1479 :   if (!calltype)
     433                 :          0 :     return unknown[object_size_type];
     434                 :            : 
     435                 :            :   /* Set to positions of alloc_size arguments.  */
     436                 :       1479 :   int arg1 = -1, arg2 = -1;
     437                 :       1479 :   tree alloc_size = lookup_attribute ("alloc_size",
     438                 :       1479 :                                       TYPE_ATTRIBUTES (calltype));
     439                 :       2817 :   if (alloc_size && TREE_VALUE (alloc_size))
     440                 :            :     {
     441                 :       1338 :       tree p = TREE_VALUE (alloc_size);
     442                 :            : 
     443                 :       1338 :       arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
     444                 :       1338 :       if (TREE_CHAIN (p))
     445                 :        152 :         arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
     446                 :            :     }
     447                 :            : 
     448                 :       1338 :   if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
     449                 :       1338 :       || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
     450                 :       2503 :       || (arg2 >= 0
     451                 :        152 :           && (arg2 >= (int)gimple_call_num_args (call)
     452                 :        152 :               || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
     453                 :        314 :     return unknown[object_size_type];
     454                 :            : 
     455                 :       1165 :   tree bytes = NULL_TREE;
     456                 :       1165 :   if (arg2 >= 0)
     457                 :        152 :     bytes = size_binop (MULT_EXPR,
     458                 :            :         fold_convert (sizetype, gimple_call_arg (call, arg1)),
     459                 :            :         fold_convert (sizetype, gimple_call_arg (call, arg2)));
     460                 :       1013 :   else if (arg1 >= 0)
     461                 :       1013 :     bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
     462                 :            : 
     463                 :       1165 :   if (bytes && tree_fits_uhwi_p (bytes))
     464                 :       1165 :     return tree_to_uhwi (bytes);
     465                 :            : 
     466                 :          0 :   return unknown[object_size_type];
     467                 :            : }
     468                 :            : 
     469                 :            : 
     470                 :            : /* If object size is propagated from one of function's arguments directly
     471                 :            :    to its return value, return that argument for GIMPLE_CALL statement CALL.
     472                 :            :    Otherwise return NULL.  */
     473                 :            : 
     474                 :            : static tree
     475                 :       1517 : pass_through_call (const gcall *call)
     476                 :            : {
     477                 :       1517 :   unsigned rf = gimple_call_return_flags (call);
     478                 :       1517 :   if (rf & ERF_RETURNS_ARG)
     479                 :            :     {
     480                 :         38 :       unsigned argnum = rf & ERF_RETURN_ARG_MASK;
     481                 :         38 :       if (argnum < gimple_call_num_args (call))
     482                 :         38 :         return gimple_call_arg (call, argnum);
     483                 :            :     }
     484                 :            : 
     485                 :            :   /* __builtin_assume_aligned is intentionally not marked RET1.  */
     486                 :       1479 :   if (gimple_call_builtin_p (call, BUILT_IN_ASSUME_ALIGNED))
     487                 :          0 :     return gimple_call_arg (call, 0);
     488                 :            : 
     489                 :            :   return NULL_TREE;
     490                 :            : }
     491                 :            : 
     492                 :            : 
     493                 :            : /* Compute __builtin_object_size value for PTR and set *PSIZE to
     494                 :            :    the resulting value.  If the declared object is known and PDECL
     495                 :            :    is nonnull, sets *PDECL to the object's DECL.  OBJECT_SIZE_TYPE
     496                 :            :    is the second argument   to __builtin_object_size.
     497                 :            :    Returns true on success and false when the object size could not
     498                 :            :    be determined.  */
     499                 :            : 
     500                 :            : bool
     501                 :    1223010 : compute_builtin_object_size (tree ptr, int object_size_type,
     502                 :            :                              unsigned HOST_WIDE_INT *psize,
     503                 :            :                              tree *pdecl /* = NULL */, tree *poff /* = NULL */)
     504                 :            : {
     505                 :    1223010 :   gcc_assert (object_size_type >= 0 && object_size_type <= 3);
     506                 :            : 
     507                 :    1223010 :   tree dummy_decl, dummy_off = size_zero_node;
     508                 :    1223010 :   if (!pdecl)
     509                 :     118374 :     pdecl = &dummy_decl;
     510                 :    1223010 :   if (!poff)
     511                 :     118374 :     poff = &dummy_off;
     512                 :            : 
     513                 :            :   /* Set to unknown and overwrite just before returning if the size
     514                 :            :      could be determined.  */
     515                 :    1223010 :   *psize = unknown[object_size_type];
     516                 :            : 
     517                 :    1223010 :   if (! offset_limit)
     518                 :      30013 :     init_offset_limit ();
     519                 :            : 
     520                 :    1223010 :   if (TREE_CODE (ptr) == ADDR_EXPR)
     521                 :     262565 :     return addr_object_size (NULL, ptr, object_size_type, psize, pdecl, poff);
     522                 :            : 
     523                 :     960443 :   if (TREE_CODE (ptr) != SSA_NAME
     524                 :    1722960 :       || !POINTER_TYPE_P (TREE_TYPE (ptr)))
     525                 :            :       return false;
     526                 :            : 
     527                 :     426023 :   if (computed[object_size_type] == NULL)
     528                 :            :     {
     529                 :     413407 :       if (optimize || object_size_type & 1)
     530                 :            :         return false;
     531                 :            : 
     532                 :            :       /* When not optimizing, rather than failing, make a small effort
     533                 :            :          to determine the object size without the full benefit of
     534                 :            :          the (costly) computation below.  */
     535                 :      13530 :       gimple *def = SSA_NAME_DEF_STMT (ptr);
     536                 :      13530 :       if (gimple_code (def) == GIMPLE_ASSIGN)
     537                 :            :         {
     538                 :      11087 :           tree_code code = gimple_assign_rhs_code (def);
     539                 :      11087 :           if (code == POINTER_PLUS_EXPR)
     540                 :            :             {
     541                 :       2724 :               tree offset = gimple_assign_rhs2 (def);
     542                 :       2724 :               ptr = gimple_assign_rhs1 (def);
     543                 :            : 
     544                 :       2724 :               if (tree_fits_shwi_p (offset)
     545                 :       2724 :                   && compute_builtin_object_size (ptr, object_size_type,
     546                 :            :                                                   psize, pdecl, poff))
     547                 :            :                 {
     548                 :            :                   /* Return zero when the offset is out of bounds.  */
     549                 :        705 :                   unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
     550                 :        705 :                   *psize = off < *psize ? *psize - off : 0;
     551                 :        705 :                   *poff = offset;
     552                 :        705 :                   return true;
     553                 :            :                 }
     554                 :            :             }
     555                 :            :         }
     556                 :      12825 :       return false;
     557                 :            :     }
     558                 :            : 
     559                 :      12616 :   if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
     560                 :            :     {
     561                 :       9142 :       struct object_size_info osi;
     562                 :       9142 :       bitmap_iterator bi;
     563                 :       9142 :       unsigned int i;
     564                 :            : 
     565                 :      27426 :       if (num_ssa_names > object_sizes[object_size_type].length ())
     566                 :       1115 :         object_sizes[object_size_type].safe_grow (num_ssa_names);
     567                 :       9142 :       if (dump_file)
     568                 :            :         {
     569                 :          2 :           fprintf (dump_file, "Computing %s %sobject size for ",
     570                 :          2 :                    (object_size_type & 2) ? "minimum" : "maximum",
     571                 :          2 :                    (object_size_type & 1) ? "sub" : "");
     572                 :          2 :           print_generic_expr (dump_file, ptr, dump_flags);
     573                 :          2 :           fprintf (dump_file, ":\n");
     574                 :            :         }
     575                 :            : 
     576                 :       9142 :       osi.visited = BITMAP_ALLOC (NULL);
     577                 :       9142 :       osi.reexamine = BITMAP_ALLOC (NULL);
     578                 :       9142 :       osi.object_size_type = object_size_type;
     579                 :       9142 :       osi.depths = NULL;
     580                 :       9142 :       osi.stack = NULL;
     581                 :       9142 :       osi.tos = NULL;
     582                 :            : 
     583                 :            :       /* First pass: walk UD chains, compute object sizes that
     584                 :            :          can be computed.  osi.reexamine bitmap at the end will
     585                 :            :          contain what variables were found in dependency cycles
     586                 :            :          and therefore need to be reexamined.  */
     587                 :       9142 :       osi.pass = 0;
     588                 :       9142 :       osi.changed = false;
     589                 :       9142 :       collect_object_sizes_for (&osi, ptr);
     590                 :            : 
     591                 :            :       /* Second pass: keep recomputing object sizes of variables
     592                 :            :          that need reexamination, until no object sizes are
     593                 :            :          increased or all object sizes are computed.  */
     594                 :       9142 :       if (! bitmap_empty_p (osi.reexamine))
     595                 :            :         {
     596                 :        282 :           bitmap reexamine = BITMAP_ALLOC (NULL);
     597                 :            : 
     598                 :            :           /* If looking for minimum instead of maximum object size,
     599                 :            :              detect cases where a pointer is increased in a loop.
     600                 :            :              Although even without this detection pass 2 would eventually
     601                 :            :              terminate, it could take a long time.  If a pointer is
     602                 :            :              increasing this way, we need to assume 0 object size.
     603                 :            :              E.g. p = &buf[0]; while (cond) p = p + 4;  */
     604                 :        282 :           if (object_size_type & 2)
     605                 :            :             {
     606                 :         32 :               osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
     607                 :         32 :               osi.stack = XNEWVEC (unsigned int, num_ssa_names);
     608                 :         16 :               osi.tos = osi.stack;
     609                 :         16 :               osi.pass = 1;
     610                 :            :               /* collect_object_sizes_for is changing
     611                 :            :                  osi.reexamine bitmap, so iterate over a copy.  */
     612                 :         16 :               bitmap_copy (reexamine, osi.reexamine);
     613                 :         46 :               EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
     614                 :         30 :                 if (bitmap_bit_p (osi.reexamine, i))
     615                 :         30 :                   check_for_plus_in_loops (&osi, ssa_name (i));
     616                 :            : 
     617                 :         16 :               free (osi.depths);
     618                 :         16 :               osi.depths = NULL;
     619                 :         16 :               free (osi.stack);
     620                 :         16 :               osi.stack = NULL;
     621                 :         16 :               osi.tos = NULL;
     622                 :            :             }
     623                 :            : 
     624                 :        316 :           do
     625                 :            :             {
     626                 :        316 :               osi.pass = 2;
     627                 :        316 :               osi.changed = false;
     628                 :            :               /* collect_object_sizes_for is changing
     629                 :            :                  osi.reexamine bitmap, so iterate over a copy.  */
     630                 :        316 :               bitmap_copy (reexamine, osi.reexamine);
     631                 :        966 :               EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
     632                 :        650 :                 if (bitmap_bit_p (osi.reexamine, i))
     633                 :            :                   {
     634                 :        650 :                     collect_object_sizes_for (&osi, ssa_name (i));
     635                 :        650 :                     if (dump_file && (dump_flags & TDF_DETAILS))
     636                 :            :                       {
     637                 :          0 :                         fprintf (dump_file, "Reexamining ");
     638                 :          0 :                         print_generic_expr (dump_file, ssa_name (i),
     639                 :            :                                             dump_flags);
     640                 :          0 :                         fprintf (dump_file, "\n");
     641                 :            :                       }
     642                 :            :                   }
     643                 :            :             }
     644                 :        316 :           while (osi.changed);
     645                 :            : 
     646                 :        282 :           BITMAP_FREE (reexamine);
     647                 :            :         }
     648                 :       9703 :       EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
     649                 :        561 :         bitmap_set_bit (computed[object_size_type], i);
     650                 :            : 
     651                 :            :       /* Debugging dumps.  */
     652                 :       9142 :       if (dump_file)
     653                 :            :         {
     654                 :          5 :           EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
     655                 :          3 :             if (object_sizes[object_size_type][i]
     656                 :          3 :                 != unknown[object_size_type])
     657                 :            :               {
     658                 :          3 :                 print_generic_expr (dump_file, ssa_name (i),
     659                 :            :                                     dump_flags);
     660                 :          3 :                 fprintf (dump_file,
     661                 :            :                          ": %s %sobject size "
     662                 :            :                          HOST_WIDE_INT_PRINT_UNSIGNED "\n",
     663                 :          3 :                          (object_size_type & 2) ? "minimum" : "maximum",
     664                 :          3 :                          (object_size_type & 1) ? "sub" : "",
     665                 :          3 :                          object_sizes[object_size_type][i]);
     666                 :            :               }
     667                 :            :         }
     668                 :            : 
     669                 :       9142 :       BITMAP_FREE (osi.reexamine);
     670                 :       9142 :       BITMAP_FREE (osi.visited);
     671                 :            :     }
     672                 :            : 
     673                 :      12616 :   *psize = object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
     674                 :      12616 :   return *psize != unknown[object_size_type];
     675                 :            : }
     676                 :            : 
     677                 :            : /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME.  */
     678                 :            : 
     679                 :            : static void
     680                 :       6685 : expr_object_size (struct object_size_info *osi, tree ptr, tree value)
     681                 :            : {
     682                 :       6685 :   int object_size_type = osi->object_size_type;
     683                 :       6685 :   unsigned int varno = SSA_NAME_VERSION (ptr);
     684                 :       6685 :   unsigned HOST_WIDE_INT bytes;
     685                 :            : 
     686                 :       6685 :   gcc_assert (object_sizes[object_size_type][varno]
     687                 :            :               != unknown[object_size_type]);
     688                 :       6685 :   gcc_assert (osi->pass == 0);
     689                 :            : 
     690                 :       6685 :   if (TREE_CODE (value) == WITH_SIZE_EXPR)
     691                 :          0 :     value = TREE_OPERAND (value, 0);
     692                 :            : 
     693                 :            :   /* Pointer variables should have been handled by merge_object_sizes.  */
     694                 :       6695 :   gcc_assert (TREE_CODE (value) != SSA_NAME
     695                 :            :               || !POINTER_TYPE_P (TREE_TYPE (value)));
     696                 :            : 
     697                 :       6685 :   if (TREE_CODE (value) == ADDR_EXPR)
     698                 :       4635 :     addr_object_size (osi, value, object_size_type, &bytes);
     699                 :            :   else
     700                 :       2050 :     bytes = unknown[object_size_type];
     701                 :            : 
     702                 :       6685 :   if ((object_size_type & 2) == 0)
     703                 :            :     {
     704                 :       5505 :       if (object_sizes[object_size_type][varno] < bytes)
     705                 :       4324 :         object_sizes[object_size_type][varno] = bytes;
     706                 :            :     }
     707                 :            :   else
     708                 :            :     {
     709                 :       1180 :       if (object_sizes[object_size_type][varno] > bytes)
     710                 :       1161 :         object_sizes[object_size_type][varno] = bytes;
     711                 :            :     }
     712                 :       6685 : }
     713                 :            : 
     714                 :            : 
     715                 :            : /* Compute object_sizes for PTR, defined to the result of a call.  */
     716                 :            : 
     717                 :            : static void
     718                 :       1479 : call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
     719                 :            : {
     720                 :       1479 :   int object_size_type = osi->object_size_type;
     721                 :       1479 :   unsigned int varno = SSA_NAME_VERSION (ptr);
     722                 :       1479 :   unsigned HOST_WIDE_INT bytes;
     723                 :            : 
     724                 :       1479 :   gcc_assert (is_gimple_call (call));
     725                 :            : 
     726                 :       1479 :   gcc_assert (object_sizes[object_size_type][varno]
     727                 :            :               != unknown[object_size_type]);
     728                 :       1479 :   gcc_assert (osi->pass == 0);
     729                 :            : 
     730                 :       1479 :   bytes = alloc_object_size (call, object_size_type);
     731                 :            : 
     732                 :       1479 :   if ((object_size_type & 2) == 0)
     733                 :            :     {
     734                 :       1221 :       if (object_sizes[object_size_type][varno] < bytes)
     735                 :       1179 :         object_sizes[object_size_type][varno] = bytes;
     736                 :            :     }
     737                 :            :   else
     738                 :            :     {
     739                 :        258 :       if (object_sizes[object_size_type][varno] > bytes)
     740                 :        258 :         object_sizes[object_size_type][varno] = bytes;
     741                 :            :     }
     742                 :       1479 : }
     743                 :            : 
     744                 :            : 
     745                 :            : /* Compute object_sizes for PTR, defined to an unknown value.  */
     746                 :            : 
     747                 :            : static void
     748                 :          0 : unknown_object_size (struct object_size_info *osi, tree ptr)
     749                 :            : {
     750                 :          0 :   int object_size_type = osi->object_size_type;
     751                 :          0 :   unsigned int varno = SSA_NAME_VERSION (ptr);
     752                 :          0 :   unsigned HOST_WIDE_INT bytes;
     753                 :            : 
     754                 :          0 :   gcc_assert (object_sizes[object_size_type][varno]
     755                 :            :               != unknown[object_size_type]);
     756                 :          0 :   gcc_assert (osi->pass == 0);
     757                 :            : 
     758                 :          0 :   bytes = unknown[object_size_type];
     759                 :            : 
     760                 :          0 :   if ((object_size_type & 2) == 0)
     761                 :            :     {
     762                 :          0 :       if (object_sizes[object_size_type][varno] < bytes)
     763                 :          0 :         object_sizes[object_size_type][varno] = bytes;
     764                 :            :     }
     765                 :            :   else
     766                 :            :     {
     767                 :          0 :       if (object_sizes[object_size_type][varno] > bytes)
     768                 :          0 :         object_sizes[object_size_type][varno] = bytes;
     769                 :            :     }
     770                 :          0 : }
     771                 :            : 
     772                 :            : 
     773                 :            : /* Merge object sizes of ORIG + OFFSET into DEST.  Return true if
     774                 :            :    the object size might need reexamination later.  */
     775                 :            : 
     776                 :            : static bool
     777                 :       2310 : merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
     778                 :            :                     unsigned HOST_WIDE_INT offset)
     779                 :            : {
     780                 :       2310 :   int object_size_type = osi->object_size_type;
     781                 :       2310 :   unsigned int varno = SSA_NAME_VERSION (dest);
     782                 :       2310 :   unsigned HOST_WIDE_INT orig_bytes;
     783                 :            : 
     784                 :       2310 :   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
     785                 :            :     return false;
     786                 :       2310 :   if (offset >= offset_limit)
     787                 :            :     {
     788                 :          2 :       object_sizes[object_size_type][varno] = unknown[object_size_type];
     789                 :          2 :       return false;
     790                 :            :     }
     791                 :            : 
     792                 :       2308 :   if (osi->pass == 0)
     793                 :       1620 :     collect_object_sizes_for (osi, orig);
     794                 :            : 
     795                 :       2308 :   orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
     796                 :       2308 :   if (orig_bytes != unknown[object_size_type])
     797                 :       1934 :     orig_bytes = (offset > orig_bytes)
     798                 :       1934 :                  ? HOST_WIDE_INT_0U : orig_bytes - offset;
     799                 :            : 
     800                 :       2308 :   if ((object_size_type & 2) == 0)
     801                 :            :     {
     802                 :       2144 :       if (object_sizes[object_size_type][varno] < orig_bytes)
     803                 :            :         {
     804                 :       1214 :           object_sizes[object_size_type][varno] = orig_bytes;
     805                 :       1214 :           osi->changed = true;
     806                 :            :         }
     807                 :            :     }
     808                 :            :   else
     809                 :            :     {
     810                 :        164 :       if (object_sizes[object_size_type][varno] > orig_bytes)
     811                 :            :         {
     812                 :        122 :           object_sizes[object_size_type][varno] = orig_bytes;
     813                 :        122 :           osi->changed = true;
     814                 :            :         }
     815                 :            :     }
     816                 :       2308 :   return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
     817                 :            : }
     818                 :            : 
     819                 :            : 
     820                 :            : /* Compute object_sizes for VAR, defined to the result of an assignment
     821                 :            :    with operator POINTER_PLUS_EXPR.  Return true if the object size might
     822                 :            :    need reexamination  later.  */
     823                 :            : 
     824                 :            : static bool
     825                 :       3054 : plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt)
     826                 :            : {
     827                 :       3054 :   int object_size_type = osi->object_size_type;
     828                 :       3054 :   unsigned int varno = SSA_NAME_VERSION (var);
     829                 :       3054 :   unsigned HOST_WIDE_INT bytes;
     830                 :       3054 :   tree op0, op1;
     831                 :            : 
     832                 :       3054 :   if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
     833                 :            :     {
     834                 :       3036 :       op0 = gimple_assign_rhs1 (stmt);
     835                 :       3036 :       op1 = gimple_assign_rhs2 (stmt);
     836                 :            :     }
     837                 :         18 :   else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
     838                 :            :     {
     839                 :         18 :       tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
     840                 :         18 :       gcc_assert (TREE_CODE (rhs) == MEM_REF);
     841                 :         18 :       op0 = TREE_OPERAND (rhs, 0);
     842                 :         18 :       op1 = TREE_OPERAND (rhs, 1);
     843                 :            :     }
     844                 :            :   else
     845                 :          0 :     gcc_unreachable ();
     846                 :            : 
     847                 :       3054 :   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
     848                 :            :     return false;
     849                 :            : 
     850                 :            :   /* Handle PTR + OFFSET here.  */
     851                 :       3054 :   if (TREE_CODE (op1) == INTEGER_CST
     852                 :       1711 :       && (TREE_CODE (op0) == SSA_NAME
     853                 :       1196 :           || TREE_CODE (op0) == ADDR_EXPR))
     854                 :            :     {
     855                 :       1706 :       if (! tree_fits_uhwi_p (op1))
     856                 :          0 :         bytes = unknown[object_size_type];
     857                 :       1706 :       else if (TREE_CODE (op0) == SSA_NAME)
     858                 :        515 :         return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1));
     859                 :            :       else
     860                 :            :         {
     861                 :       1191 :           unsigned HOST_WIDE_INT off = tree_to_uhwi (op1);
     862                 :            : 
     863                 :            :           /* op0 will be ADDR_EXPR here.  */
     864                 :       1191 :           addr_object_size (osi, op0, object_size_type, &bytes);
     865                 :       1191 :           if (bytes == unknown[object_size_type])
     866                 :            :             ;
     867                 :       1185 :           else if (off > offset_limit)
     868                 :          0 :             bytes = unknown[object_size_type];
     869                 :       1185 :           else if (off > bytes)
     870                 :          0 :             bytes = 0;
     871                 :            :           else
     872                 :       1185 :             bytes -= off;
     873                 :            :         }
     874                 :            :     }
     875                 :            :   else
     876                 :       1348 :     bytes = unknown[object_size_type];
     877                 :            : 
     878                 :       2539 :   if ((object_size_type & 2) == 0)
     879                 :            :     {
     880                 :       2534 :       if (object_sizes[object_size_type][varno] < bytes)
     881                 :       2402 :         object_sizes[object_size_type][varno] = bytes;
     882                 :            :     }
     883                 :            :   else
     884                 :            :     {
     885                 :          5 :       if (object_sizes[object_size_type][varno] > bytes)
     886                 :          5 :         object_sizes[object_size_type][varno] = bytes;
     887                 :            :     }
     888                 :            :   return false;
     889                 :            : }
     890                 :            : 
     891                 :            : 
     892                 :            : /* Compute object_sizes for VAR, defined at STMT, which is
     893                 :            :    a COND_EXPR.  Return true if the object size might need reexamination
     894                 :            :    later.  */
     895                 :            : 
     896                 :            : static bool
     897                 :          0 : cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt)
     898                 :            : {
     899                 :          0 :   tree then_, else_;
     900                 :          0 :   int object_size_type = osi->object_size_type;
     901                 :          0 :   unsigned int varno = SSA_NAME_VERSION (var);
     902                 :          0 :   bool reexamine = false;
     903                 :            : 
     904                 :          0 :   gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
     905                 :            : 
     906                 :          0 :   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
     907                 :            :     return false;
     908                 :            : 
     909                 :          0 :   then_ = gimple_assign_rhs2 (stmt);
     910                 :          0 :   else_ = gimple_assign_rhs3 (stmt);
     911                 :            : 
     912                 :          0 :   if (TREE_CODE (then_) == SSA_NAME)
     913                 :          0 :     reexamine |= merge_object_sizes (osi, var, then_, 0);
     914                 :            :   else
     915                 :          0 :     expr_object_size (osi, var, then_);
     916                 :            : 
     917                 :          0 :   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
     918                 :            :     return reexamine;
     919                 :            : 
     920                 :          0 :   if (TREE_CODE (else_) == SSA_NAME)
     921                 :          0 :     reexamine |= merge_object_sizes (osi, var, else_, 0);
     922                 :            :   else
     923                 :          0 :     expr_object_size (osi, var, else_);
     924                 :            : 
     925                 :            :   return reexamine;
     926                 :            : }
     927                 :            : 
     928                 :            : /* Compute object sizes for VAR.
     929                 :            :    For ADDR_EXPR an object size is the number of remaining bytes
     930                 :            :    to the end of the object (where what is considered an object depends on
     931                 :            :    OSI->object_size_type).
     932                 :            :    For allocation GIMPLE_CALL like malloc or calloc object size is the size
     933                 :            :    of the allocation.
     934                 :            :    For POINTER_PLUS_EXPR where second operand is a constant integer,
     935                 :            :    object size is object size of the first operand minus the constant.
     936                 :            :    If the constant is bigger than the number of remaining bytes until the
     937                 :            :    end of the object, object size is 0, but if it is instead a pointer
     938                 :            :    subtraction, object size is unknown[object_size_type].
     939                 :            :    To differentiate addition from subtraction, ADDR_EXPR returns
     940                 :            :    unknown[object_size_type] for all objects bigger than half of the address
     941                 :            :    space, and constants less than half of the address space are considered
     942                 :            :    addition, while bigger constants subtraction.
     943                 :            :    For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
     944                 :            :    object size is object size of that argument.
     945                 :            :    Otherwise, object size is the maximum of object sizes of variables
     946                 :            :    that it might be set to.  */
     947                 :            : 
     948                 :            : static void
     949                 :      12212 : collect_object_sizes_for (struct object_size_info *osi, tree var)
     950                 :            : {
     951                 :      12212 :   int object_size_type = osi->object_size_type;
     952                 :      12212 :   unsigned int varno = SSA_NAME_VERSION (var);
     953                 :      12212 :   gimple *stmt;
     954                 :      12212 :   bool reexamine;
     955                 :            : 
     956                 :      12212 :   if (bitmap_bit_p (computed[object_size_type], varno))
     957                 :            :     return;
     958                 :            : 
     959                 :      11414 :   if (osi->pass == 0)
     960                 :            :     {
     961                 :      10764 :       if (bitmap_set_bit (osi->visited, varno))
     962                 :            :         {
     963                 :      10476 :           object_sizes[object_size_type][varno]
     964                 :      20952 :             = (object_size_type & 2) ? -1 : 0;
     965                 :            :         }
     966                 :            :       else
     967                 :            :         {
     968                 :            :           /* Found a dependency loop.  Mark the variable for later
     969                 :            :              re-examination.  */
     970                 :        288 :           bitmap_set_bit (osi->reexamine, varno);
     971                 :        288 :           if (dump_file && (dump_flags & TDF_DETAILS))
     972                 :            :             {
     973                 :          0 :               fprintf (dump_file, "Found a dependency loop at ");
     974                 :          0 :               print_generic_expr (dump_file, var, dump_flags);
     975                 :          0 :               fprintf (dump_file, "\n");
     976                 :            :             }
     977                 :        288 :           return;
     978                 :            :         }
     979                 :            :     }
     980                 :            : 
     981                 :      11126 :   if (dump_file && (dump_flags & TDF_DETAILS))
     982                 :            :     {
     983                 :          3 :       fprintf (dump_file, "Visiting use-def links for ");
     984                 :          3 :       print_generic_expr (dump_file, var, dump_flags);
     985                 :          3 :       fprintf (dump_file, "\n");
     986                 :            :     }
     987                 :            : 
     988                 :      11126 :   stmt = SSA_NAME_DEF_STMT (var);
     989                 :      11126 :   reexamine = false;
     990                 :            : 
     991                 :      11126 :   switch (gimple_code (stmt))
     992                 :            :     {
     993                 :       6440 :     case GIMPLE_ASSIGN:
     994                 :       6440 :       {
     995                 :       6440 :         tree rhs = gimple_assign_rhs1 (stmt);
     996                 :       6440 :         if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
     997                 :       6440 :             || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
     998                 :       2661 :                 && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
     999                 :       3054 :           reexamine = plus_stmt_object_size (osi, var, stmt);
    1000                 :       3386 :         else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
    1001                 :          0 :           reexamine = cond_expr_object_size (osi, var, stmt);
    1002                 :       3386 :         else if (gimple_assign_single_p (stmt)
    1003                 :         10 :                  || gimple_assign_unary_nop_p (stmt))
    1004                 :            :           {
    1005                 :       3386 :             if (TREE_CODE (rhs) == SSA_NAME
    1006                 :       3503 :                 && POINTER_TYPE_P (TREE_TYPE (rhs)))
    1007                 :        107 :               reexamine = merge_object_sizes (osi, var, rhs, 0);
    1008                 :            :             else
    1009                 :       3279 :               expr_object_size (osi, var, rhs);
    1010                 :            :           }
    1011                 :            :         else
    1012                 :          0 :           unknown_object_size (osi, var);
    1013                 :            :         break;
    1014                 :            :       }
    1015                 :            : 
    1016                 :       1517 :     case GIMPLE_CALL:
    1017                 :       1517 :       {
    1018                 :       1517 :         gcall *call_stmt = as_a <gcall *> (stmt);
    1019                 :       1517 :         tree arg = pass_through_call (call_stmt);
    1020                 :       1517 :         if (arg)
    1021                 :            :           {
    1022                 :         38 :             if (TREE_CODE (arg) == SSA_NAME
    1023                 :         67 :                 && POINTER_TYPE_P (TREE_TYPE (arg)))
    1024                 :         29 :               reexamine = merge_object_sizes (osi, var, arg, 0);
    1025                 :            :             else
    1026                 :          9 :               expr_object_size (osi, var, arg);
    1027                 :            :           }
    1028                 :            :         else
    1029                 :       1479 :           call_object_size (osi, var, call_stmt);
    1030                 :            :         break;
    1031                 :            :       }
    1032                 :            : 
    1033                 :          0 :     case GIMPLE_ASM:
    1034                 :            :       /* Pointers defined by __asm__ statements can point anywhere.  */
    1035                 :          0 :       object_sizes[object_size_type][varno] = unknown[object_size_type];
    1036                 :          0 :       break;
    1037                 :            : 
    1038                 :       1429 :     case GIMPLE_NOP:
    1039                 :       1429 :       if (SSA_NAME_VAR (var)
    1040                 :       1429 :           && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
    1041                 :       1414 :         expr_object_size (osi, var, SSA_NAME_VAR (var));
    1042                 :            :       else
    1043                 :            :         /* Uninitialized SSA names point nowhere.  */
    1044                 :         15 :         object_sizes[object_size_type][varno] = unknown[object_size_type];
    1045                 :            :       break;
    1046                 :            : 
    1047                 :            :     case GIMPLE_PHI:
    1048                 :            :       {
    1049                 :            :         unsigned i;
    1050                 :            : 
    1051                 :       6753 :         for (i = 0; i < gimple_phi_num_args (stmt); i++)
    1052                 :            :           {
    1053                 :       5094 :             tree rhs = gimple_phi_arg (stmt, i)->def;
    1054                 :            : 
    1055                 :       5094 :             if (object_sizes[object_size_type][varno]
    1056                 :       5094 :                 == unknown[object_size_type])
    1057                 :            :               break;
    1058                 :            : 
    1059                 :       5013 :             if (TREE_CODE (rhs) == SSA_NAME)
    1060                 :       1659 :               reexamine |= merge_object_sizes (osi, var, rhs, 0);
    1061                 :       3354 :             else if (osi->pass == 0)
    1062                 :       1983 :               expr_object_size (osi, var, rhs);
    1063                 :            :           }
    1064                 :            :         break;
    1065                 :            :       }
    1066                 :            : 
    1067                 :          0 :     default:
    1068                 :          0 :       gcc_unreachable ();
    1069                 :            :     }
    1070                 :            : 
    1071                 :       6196 :   if (! reexamine
    1072                 :       4930 :       || object_sizes[object_size_type][varno] == unknown[object_size_type])
    1073                 :            :     {
    1074                 :       9901 :       bitmap_set_bit (computed[object_size_type], varno);
    1075                 :       9901 :       bitmap_clear_bit (osi->reexamine, varno);
    1076                 :            :     }
    1077                 :            :   else
    1078                 :            :     {
    1079                 :       1225 :       bitmap_set_bit (osi->reexamine, varno);
    1080                 :       1225 :       if (dump_file && (dump_flags & TDF_DETAILS))
    1081                 :            :         {
    1082                 :          0 :           fprintf (dump_file, "Need to reexamine ");
    1083                 :          0 :           print_generic_expr (dump_file, var, dump_flags);
    1084                 :          0 :           fprintf (dump_file, "\n");
    1085                 :            :         }
    1086                 :            :     }
    1087                 :            : }
    1088                 :            : 
    1089                 :            : 
    1090                 :            : /* Helper function for check_for_plus_in_loops.  Called recursively
    1091                 :            :    to detect loops.  */
    1092                 :            : 
    1093                 :            : static void
    1094                 :         14 : check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
    1095                 :            :                            unsigned int depth)
    1096                 :            : {
    1097                 :         14 :   gimple *stmt = SSA_NAME_DEF_STMT (var);
    1098                 :         14 :   unsigned int varno = SSA_NAME_VERSION (var);
    1099                 :            : 
    1100                 :         14 :   if (osi->depths[varno])
    1101                 :            :     {
    1102                 :          7 :       if (osi->depths[varno] != depth)
    1103                 :            :         {
    1104                 :          7 :           unsigned int *sp;
    1105                 :            : 
    1106                 :            :           /* Found a loop involving pointer addition.  */
    1107                 :         14 :           for (sp = osi->tos; sp > osi->stack; )
    1108                 :            :             {
    1109                 :         14 :               --sp;
    1110                 :         14 :               bitmap_clear_bit (osi->reexamine, *sp);
    1111                 :         14 :               bitmap_set_bit (computed[osi->object_size_type], *sp);
    1112                 :         14 :               object_sizes[osi->object_size_type][*sp] = 0;
    1113                 :         14 :               if (*sp == varno)
    1114                 :            :                 break;
    1115                 :            :             }
    1116                 :            :         }
    1117                 :          7 :       return;
    1118                 :            :     }
    1119                 :          7 :   else if (! bitmap_bit_p (osi->reexamine, varno))
    1120                 :            :     return;
    1121                 :            : 
    1122                 :          7 :   osi->depths[varno] = depth;
    1123                 :          7 :   *osi->tos++ = varno;
    1124                 :            : 
    1125                 :          7 :   switch (gimple_code (stmt))
    1126                 :            :     {
    1127                 :            : 
    1128                 :          7 :     case GIMPLE_ASSIGN:
    1129                 :          7 :       {
    1130                 :          7 :         if ((gimple_assign_single_p (stmt)
    1131                 :          7 :              || gimple_assign_unary_nop_p (stmt))
    1132                 :          0 :             && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
    1133                 :            :           {
    1134                 :          0 :             tree rhs = gimple_assign_rhs1 (stmt);
    1135                 :            : 
    1136                 :          0 :             check_for_plus_in_loops_1 (osi, rhs, depth);
    1137                 :            :           }
    1138                 :          7 :         else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
    1139                 :            :           {
    1140                 :          7 :             tree basevar = gimple_assign_rhs1 (stmt);
    1141                 :          7 :             tree cst = gimple_assign_rhs2 (stmt);
    1142                 :            : 
    1143                 :          7 :             gcc_assert (TREE_CODE (cst) == INTEGER_CST);
    1144                 :            : 
    1145                 :         14 :             check_for_plus_in_loops_1 (osi, basevar,
    1146                 :          7 :                                        depth + !integer_zerop (cst));
    1147                 :            :           }
    1148                 :            :         else
    1149                 :          0 :           gcc_unreachable ();
    1150                 :            :         break;
    1151                 :            :       }
    1152                 :            : 
    1153                 :          0 :     case GIMPLE_CALL:
    1154                 :          0 :       {
    1155                 :          0 :         gcall *call_stmt = as_a <gcall *> (stmt);
    1156                 :          0 :         tree arg = pass_through_call (call_stmt);
    1157                 :          0 :         if (arg)
    1158                 :            :           {
    1159                 :          0 :             if (TREE_CODE (arg) == SSA_NAME)
    1160                 :          0 :               check_for_plus_in_loops_1 (osi, arg, depth);
    1161                 :            :             else
    1162                 :          0 :               gcc_unreachable ();
    1163                 :            :           }
    1164                 :            :         break;
    1165                 :            :       }
    1166                 :            : 
    1167                 :            :     case GIMPLE_PHI:
    1168                 :            :       {
    1169                 :            :         unsigned i;
    1170                 :            : 
    1171                 :          0 :         for (i = 0; i < gimple_phi_num_args (stmt); i++)
    1172                 :            :           {
    1173                 :          0 :             tree rhs = gimple_phi_arg (stmt, i)->def;
    1174                 :            : 
    1175                 :          0 :             if (TREE_CODE (rhs) == SSA_NAME)
    1176                 :          0 :               check_for_plus_in_loops_1 (osi, rhs, depth);
    1177                 :            :           }
    1178                 :            :         break;
    1179                 :            :       }
    1180                 :            : 
    1181                 :          0 :     default:
    1182                 :          0 :       gcc_unreachable ();
    1183                 :            :     }
    1184                 :            : 
    1185                 :          7 :   osi->depths[varno] = 0;
    1186                 :          7 :   osi->tos--;
    1187                 :            : }
    1188                 :            : 
    1189                 :            : 
    1190                 :            : /* Check if some pointer we are computing object size of is being increased
    1191                 :            :    within a loop.  If yes, assume all the SSA variables participating in
    1192                 :            :    that loop have minimum object sizes 0.  */
    1193                 :            : 
    1194                 :            : static void
    1195                 :         30 : check_for_plus_in_loops (struct object_size_info *osi, tree var)
    1196                 :            : {
    1197                 :         30 :   gimple *stmt = SSA_NAME_DEF_STMT (var);
    1198                 :            : 
    1199                 :            :   /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
    1200                 :            :      and looked for a POINTER_PLUS_EXPR in the pass-through
    1201                 :            :      argument, if any.  In GIMPLE, however, such an expression
    1202                 :            :      is not a valid call operand.  */
    1203                 :            : 
    1204                 :         30 :   if (is_gimple_assign (stmt)
    1205                 :         30 :       && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
    1206                 :            :     {
    1207                 :          7 :       tree basevar = gimple_assign_rhs1 (stmt);
    1208                 :          7 :       tree cst = gimple_assign_rhs2 (stmt);
    1209                 :            : 
    1210                 :          7 :       gcc_assert (TREE_CODE (cst) == INTEGER_CST);
    1211                 :            : 
    1212                 :          7 :       if (integer_zerop (cst))
    1213                 :            :         return;
    1214                 :            : 
    1215                 :          7 :       osi->depths[SSA_NAME_VERSION (basevar)] = 1;
    1216                 :          7 :       *osi->tos++ = SSA_NAME_VERSION (basevar);
    1217                 :          7 :       check_for_plus_in_loops_1 (osi, var, 2);
    1218                 :          7 :       osi->depths[SSA_NAME_VERSION (basevar)] = 0;
    1219                 :          7 :       osi->tos--;
    1220                 :            :     }
    1221                 :            : }
    1222                 :            : 
    1223                 :            : 
    1224                 :            : /* Initialize data structures for the object size computation.  */
    1225                 :            : 
    1226                 :            : void
    1227                 :      19326 : init_object_sizes (void)
    1228                 :            : {
    1229                 :      19326 :   int object_size_type;
    1230                 :            : 
    1231                 :      19326 :   if (computed[0])
    1232                 :            :     return;
    1233                 :            : 
    1234                 :      21530 :   for (object_size_type = 0; object_size_type <= 3; object_size_type++)
    1235                 :            :     {
    1236                 :      34448 :       object_sizes[object_size_type].safe_grow (num_ssa_names);
    1237                 :      17224 :       computed[object_size_type] = BITMAP_ALLOC (NULL);
    1238                 :            :     }
    1239                 :            : 
    1240                 :       4306 :   init_offset_limit ();
    1241                 :            : }
    1242                 :            : 
    1243                 :            : 
    1244                 :            : /* Destroy data structures after the object size computation.  */
    1245                 :            : 
    1246                 :            : void
    1247                 :    2981880 : fini_object_sizes (void)
    1248                 :            : {
    1249                 :    2981880 :   int object_size_type;
    1250                 :            : 
    1251                 :   14909400 :   for (object_size_type = 0; object_size_type <= 3; object_size_type++)
    1252                 :            :     {
    1253                 :   11927500 :       object_sizes[object_size_type].release ();
    1254                 :   11927500 :       BITMAP_FREE (computed[object_size_type]);
    1255                 :            :     }
    1256                 :    2981880 : }
    1257                 :            : 
    1258                 :            : 
    1259                 :            : /* Simple pass to optimize all __builtin_object_size () builtins.  */
    1260                 :            : 
    1261                 :            : namespace {
    1262                 :            : 
    1263                 :            : const pass_data pass_data_object_sizes =
    1264                 :            : {
    1265                 :            :   GIMPLE_PASS, /* type */
    1266                 :            :   "objsz", /* name */
    1267                 :            :   OPTGROUP_NONE, /* optinfo_flags */
    1268                 :            :   TV_NONE, /* tv_id */
    1269                 :            :   ( PROP_cfg | PROP_ssa ), /* properties_required */
    1270                 :            :   0, /* properties_provided */
    1271                 :            :   0, /* properties_destroyed */
    1272                 :            :   0, /* todo_flags_start */
    1273                 :            :   0, /* todo_flags_finish */
    1274                 :            : };
    1275                 :            : 
    1276                 :            : class pass_object_sizes : public gimple_opt_pass
    1277                 :            : {
    1278                 :            : public:
    1279                 :     602319 :   pass_object_sizes (gcc::context *ctxt)
    1280                 :    1204640 :     : gimple_opt_pass (pass_data_object_sizes, ctxt), insert_min_max_p (false)
    1281                 :            :   {}
    1282                 :            : 
    1283                 :            :   /* opt_pass methods: */
    1284                 :     401546 :   opt_pass * clone () { return new pass_object_sizes (m_ctxt); }
    1285                 :     401546 :   void set_pass_param (unsigned int n, bool param)
    1286                 :            :     {
    1287                 :     401546 :       gcc_assert (n == 0);
    1288                 :     401546 :       insert_min_max_p = param;
    1289                 :     401546 :     }
    1290                 :            :   virtual unsigned int execute (function *);
    1291                 :            : 
    1292                 :            :  private:
    1293                 :            :   /* Determines whether the pass instance creates MIN/MAX_EXPRs.  */
    1294                 :            :   bool insert_min_max_p;
    1295                 :            : }; // class pass_object_sizes
    1296                 :            : 
    1297                 :            : /* Dummy valueize function.  */
    1298                 :            : 
    1299                 :            : static tree
    1300                 :      17151 : do_valueize (tree t)
    1301                 :            : {
    1302                 :      17151 :   return t;
    1303                 :            : }
    1304                 :            : 
    1305                 :            : unsigned int
    1306                 :    2279280 : pass_object_sizes::execute (function *fun)
    1307                 :            : {
    1308                 :    2279280 :   basic_block bb;
    1309                 :   18947300 :   FOR_EACH_BB_FN (bb, fun)
    1310                 :            :     {
    1311                 :   16668000 :       gimple_stmt_iterator i;
    1312                 :  146988000 :       for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
    1313                 :            :         {
    1314                 :  113652000 :           tree result;
    1315                 :  113652000 :           gimple *call = gsi_stmt (i);
    1316                 :  113652000 :           if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
    1317                 :  113638000 :             continue;
    1318                 :            : 
    1319                 :      13519 :           init_object_sizes ();
    1320                 :            : 
    1321                 :            :           /* If insert_min_max_p, only attempt to fold
    1322                 :            :              __builtin_object_size (x, 1) and __builtin_object_size (x, 3),
    1323                 :            :              and rather than folding the builtin to the constant if any,
    1324                 :            :              create a MIN_EXPR or MAX_EXPR of the __builtin_object_size
    1325                 :            :              call result and the computed constant.  */
    1326                 :      13519 :           if (insert_min_max_p)
    1327                 :            :             {
    1328                 :       9225 :               tree ost = gimple_call_arg (call, 1);
    1329                 :       9225 :               if (tree_fits_uhwi_p (ost))
    1330                 :            :                 {
    1331                 :       9225 :                   unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
    1332                 :       9225 :                   tree ptr = gimple_call_arg (call, 0);
    1333                 :       9225 :                   tree lhs = gimple_call_lhs (call);
    1334                 :       9225 :                   if ((object_size_type == 1 || object_size_type == 3)
    1335                 :       2508 :                       && (TREE_CODE (ptr) == ADDR_EXPR
    1336                 :       2508 :                           || TREE_CODE (ptr) == SSA_NAME)
    1337                 :       2508 :                       && lhs)
    1338                 :            :                     {
    1339                 :       2508 :                       tree type = TREE_TYPE (lhs);
    1340                 :       2508 :                       unsigned HOST_WIDE_INT bytes;
    1341                 :       2508 :                       if (compute_builtin_object_size (ptr, object_size_type,
    1342                 :            :                                                        &bytes)
    1343                 :       2508 :                           && wi::fits_to_tree_p (bytes, type))
    1344                 :            :                         {
    1345                 :       1176 :                           tree tem = make_ssa_name (type);
    1346                 :       1176 :                           gimple_call_set_lhs (call, tem);
    1347                 :       2352 :                           enum tree_code code
    1348                 :       1176 :                             = object_size_type == 1 ? MIN_EXPR : MAX_EXPR;
    1349                 :       1176 :                           tree cst = build_int_cstu (type, bytes);
    1350                 :       1176 :                           gimple *g
    1351                 :       1176 :                             = gimple_build_assign (lhs, code, tem, cst);
    1352                 :       1176 :                           gsi_insert_after (&i, g, GSI_NEW_STMT);
    1353                 :       3684 :                           update_stmt (call);
    1354                 :            :                         }
    1355                 :            :                     }
    1356                 :            :                 }
    1357                 :       9225 :               continue;
    1358                 :            :             }
    1359                 :            : 
    1360                 :       4294 :           tree lhs = gimple_call_lhs (call);
    1361                 :       4294 :           if (!lhs)
    1362                 :          0 :             continue;
    1363                 :            : 
    1364                 :       4294 :           result = gimple_fold_stmt_to_constant (call, do_valueize);
    1365                 :       4294 :           if (!result)
    1366                 :            :             {
    1367                 :       2027 :               tree ost = gimple_call_arg (call, 1);
    1368                 :            : 
    1369                 :       2027 :               if (tree_fits_uhwi_p (ost))
    1370                 :            :                 {
    1371                 :       2027 :                   unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
    1372                 :            : 
    1373                 :       2027 :                   if (object_size_type < 2)
    1374                 :       1877 :                     result = fold_convert (size_type_node,
    1375                 :            :                                            integer_minus_one_node);
    1376                 :        150 :                   else if (object_size_type < 4)
    1377                 :        150 :                     result = build_zero_cst (size_type_node);
    1378                 :            :                 }
    1379                 :            : 
    1380                 :       2027 :               if (!result)
    1381                 :          0 :                 continue;
    1382                 :            :             }
    1383                 :            : 
    1384                 :       4294 :           gcc_assert (TREE_CODE (result) == INTEGER_CST);
    1385                 :            : 
    1386                 :       4294 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1387                 :            :             {
    1388                 :          0 :               fprintf (dump_file, "Simplified\n  ");
    1389                 :          0 :               print_gimple_stmt (dump_file, call, 0, dump_flags);
    1390                 :          0 :               fprintf (dump_file, " to ");
    1391                 :          0 :               print_generic_expr (dump_file, result);
    1392                 :          0 :               fprintf (dump_file, "\n");
    1393                 :            :             }
    1394                 :            : 
    1395                 :            :           /* Propagate into all uses and fold those stmts.  */
    1396                 :       4294 :           if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
    1397                 :       4287 :             replace_uses_by (lhs, result);
    1398                 :            :           else
    1399                 :          7 :             replace_call_with_value (&i, result);
    1400                 :            :         }
    1401                 :            :     }
    1402                 :            : 
    1403                 :    2279280 :   fini_object_sizes ();
    1404                 :    2279280 :   return 0;
    1405                 :            : }
    1406                 :            : 
    1407                 :            : } // anon namespace
    1408                 :            : 
    1409                 :            : gimple_opt_pass *
    1410                 :     200773 : make_pass_object_sizes (gcc::context *ctxt)
    1411                 :            : {
    1412                 :     200773 :   return new pass_object_sizes (ctxt);
    1413                 :            : }

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.