LCOV - code coverage report
Current view: top level - gcc - ipa-polymorphic-call.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.0 % 1201 997
Test Date: 2024-04-13 14:00:49 Functions: 96.6 % 29 28
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Analysis of polymorphic call context.
       2                 :             :    Copyright (C) 2013-2024 Free Software Foundation, Inc.
       3                 :             :    Contributed by Jan Hubicka
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify it under
       8                 :             : the terms of the GNU General Public License as published by the Free
       9                 :             : Software Foundation; either version 3, or (at your option) any later
      10                 :             : version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15                 :             : 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 "rtl.h"
      26                 :             : #include "tree.h"
      27                 :             : #include "gimple.h"
      28                 :             : #include "tree-pass.h"
      29                 :             : #include "tree-ssa-operands.h"
      30                 :             : #include "streamer-hooks.h"
      31                 :             : #include "cgraph.h"
      32                 :             : #include "data-streamer.h"
      33                 :             : #include "diagnostic.h"
      34                 :             : #include "alias.h"
      35                 :             : #include "fold-const.h"
      36                 :             : #include "calls.h"
      37                 :             : #include "ipa-utils.h"
      38                 :             : #include "tree-dfa.h"
      39                 :             : #include "gimple-pretty-print.h"
      40                 :             : #include "tree-into-ssa.h"
      41                 :             : #include "alloc-pool.h"
      42                 :             : #include "symbol-summary.h"
      43                 :             : #include "symtab-thunks.h"
      44                 :             : 
      45                 :             : /* Return true when TYPE contains an polymorphic type and thus is interesting
      46                 :             :    for devirtualization machinery.  */
      47                 :             : 
      48                 :             : static bool contains_type_p (tree, HOST_WIDE_INT, tree,
      49                 :             :                              bool consider_placement_new = true,
      50                 :             :                              bool consider_bases = true);
      51                 :             : 
      52                 :             : bool
      53                 :    32984623 : contains_polymorphic_type_p (const_tree type)
      54                 :             : {
      55                 :    37989709 :   type = TYPE_MAIN_VARIANT (type);
      56                 :             : 
      57                 :    37989709 :   if (RECORD_OR_UNION_TYPE_P (type))
      58                 :             :     {
      59                 :     8577461 :       if (TYPE_BINFO (type)
      60                 :     8577461 :           && polymorphic_type_binfo_p (TYPE_BINFO (type)))
      61                 :             :         return true;
      62                 :   365266865 :       for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
      63                 :   357969463 :         if (TREE_CODE (fld) == FIELD_DECL
      64                 :    29434246 :             && !DECL_ARTIFICIAL (fld)
      65                 :   385312304 :             && contains_polymorphic_type_p (TREE_TYPE (fld)))
      66                 :             :           return true;
      67                 :             :       return false;
      68                 :             :     }
      69                 :    29412248 :   if (TREE_CODE (type) == ARRAY_TYPE)
      70                 :     5005086 :     return contains_polymorphic_type_p (TREE_TYPE (type));
      71                 :             :   return false;
      72                 :             : }
      73                 :             : 
      74                 :             : /* Return true if it seems valid to use placement new to build EXPECTED_TYPE
      75                 :             :    at position CUR_OFFSET within TYPE.  
      76                 :             : 
      77                 :             :    POD can be changed to an instance of a polymorphic type by
      78                 :             :    placement new.  Here we play safe and assume that any
      79                 :             :    non-polymorphic type is POD.  */
      80                 :             : bool
      81                 :      105471 : possible_placement_new (tree type, tree expected_type,
      82                 :             :                         HOST_WIDE_INT cur_offset)
      83                 :             : {
      84                 :      105471 :   if (cur_offset < 0)
      85                 :             :     return true;
      86                 :      102003 :   return ((TREE_CODE (type) != RECORD_TYPE
      87                 :       12715 :            || !TYPE_BINFO (type)
      88                 :       12775 :            || cur_offset >= POINTER_SIZE
      89                 :       10345 :            || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
      90                 :      114630 :           && (!TYPE_SIZE (type)
      91                 :      101915 :               || !tree_fits_shwi_p (TYPE_SIZE (type))
      92                 :      203830 :               || (cur_offset
      93                 :      101915 :                   + (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
      94                 :       91841 :                      : POINTER_SIZE)
      95                 :      101915 :                   <= tree_to_uhwi (TYPE_SIZE (type)))));
      96                 :             : }
      97                 :             : 
      98                 :             : /* THIS->OUTER_TYPE is a type of memory object where object of OTR_TYPE
      99                 :             :    is contained at THIS->OFFSET.  Walk the memory representation of
     100                 :             :    THIS->OUTER_TYPE and find the outermost class type that match
     101                 :             :    OTR_TYPE or contain OTR_TYPE as a base.  Update THIS
     102                 :             :    to represent it.
     103                 :             : 
     104                 :             :    If OTR_TYPE is NULL, just find outermost polymorphic type with
     105                 :             :    virtual table present at position OFFSET.
     106                 :             : 
     107                 :             :    For example when THIS represents type
     108                 :             :    class A
     109                 :             :      {
     110                 :             :        int a;
     111                 :             :        class B b;
     112                 :             :      }
     113                 :             :    and we look for type at offset sizeof(int), we end up with B and offset 0.
     114                 :             :    If the same is produced by multiple inheritance, we end up with A and offset
     115                 :             :    sizeof(int). 
     116                 :             : 
     117                 :             :    If we cannot find corresponding class, give up by setting
     118                 :             :    THIS->OUTER_TYPE to OTR_TYPE and THIS->OFFSET to NULL. 
     119                 :             :    Return true when lookup was successful.
     120                 :             : 
     121                 :             :    When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
     122                 :             :    valid only via allocation of new polymorphic type inside by means
     123                 :             :    of placement new.
     124                 :             : 
     125                 :             :    When CONSIDER_BASES is false, only look for actual fields, not base types
     126                 :             :    of TYPE.  */
     127                 :             : 
     128                 :             : bool
     129                 :     1905232 : ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
     130                 :             :                                                        bool consider_placement_new,
     131                 :             :                                                        bool consider_bases)
     132                 :             : {
     133                 :     1905232 :   tree type = outer_type;
     134                 :     1905232 :   HOST_WIDE_INT cur_offset = offset;
     135                 :     1905232 :   bool speculative = false;
     136                 :     1905232 :   bool size_unknown = false;
     137                 :     1905232 :   unsigned HOST_WIDE_INT otr_type_size = POINTER_SIZE;
     138                 :             : 
     139                 :             :   /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set.  */
     140                 :     1905232 :   if (!outer_type)
     141                 :             :     {
     142                 :       62075 :       clear_outer_type (otr_type);
     143                 :       62075 :       type = otr_type;
     144                 :       62075 :       cur_offset = 0;
     145                 :             :     }
     146                 :             :  /* See if OFFSET points inside OUTER_TYPE.  If it does not, we know
     147                 :             :     that the context is either invalid, or the instance type must be
     148                 :             :     derived from OUTER_TYPE.
     149                 :             : 
     150                 :             :     Because the instance type may contain field whose type is of OUTER_TYPE,
     151                 :             :     we cannot derive any effective information about it.
     152                 :             : 
     153                 :             :     TODO: In the case we know all derived types, we can definitely do better
     154                 :             :     here.  */
     155                 :     1843157 :   else if (TYPE_SIZE (outer_type)
     156                 :     1843134 :            && tree_fits_shwi_p (TYPE_SIZE (outer_type))
     157                 :     1843134 :            && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
     158                 :     3686291 :            && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
     159                 :             :    {
     160                 :          12 :      bool der = maybe_derived_type; /* clear_outer_type will reset it.  */
     161                 :          12 :      bool dyn = dynamic;
     162                 :          12 :      clear_outer_type (otr_type);
     163                 :          12 :      type = otr_type;
     164                 :          12 :      cur_offset = 0;
     165                 :             : 
     166                 :             :      /* If derived type is not allowed, we know that the context is invalid.
     167                 :             :         For dynamic types, we really do not have information about
     168                 :             :         size of the memory location.  It is possible that completely
     169                 :             :         different type is stored after outer_type.  */
     170                 :          12 :      if (!der && !dyn)
     171                 :             :        {
     172                 :          12 :          clear_speculation ();
     173                 :          12 :          invalid = true;
     174                 :          12 :          return false;
     175                 :             :        }
     176                 :             :    }
     177                 :             : 
     178                 :     1809371 :   if (otr_type && TYPE_SIZE (otr_type)
     179                 :     3714586 :       && tree_fits_shwi_p (TYPE_SIZE (otr_type)))
     180                 :     1809366 :     otr_type_size = tree_to_uhwi (TYPE_SIZE (otr_type));
     181                 :             : 
     182                 :     1905220 :   if (!type || offset < 0)
     183                 :        3468 :     goto no_useful_type_info;
     184                 :             : 
     185                 :             :   /* Find the sub-object the constant actually refers to and mark whether it is
     186                 :             :      an artificial one (as opposed to a user-defined one).
     187                 :             : 
     188                 :             :      This loop is performed twice; first time for outer_type and second time
     189                 :             :      for speculative_outer_type.  The second run has SPECULATIVE set.  */
     190                 :     2374599 :   while (true)
     191                 :             :     {
     192                 :     2374599 :       unsigned HOST_WIDE_INT pos, size;
     193                 :     2374599 :       tree fld;
     194                 :             : 
     195                 :             :       /* If we do not know size of TYPE, we need to be more conservative
     196                 :             :          about accepting cases where we cannot find EXPECTED_TYPE.
     197                 :             :          Generally the types that do matter here are of constant size.
     198                 :             :          Size_unknown case should be very rare.  */
     199                 :     2374599 :       if (TYPE_SIZE (type)
     200                 :     2374576 :           && tree_fits_shwi_p (TYPE_SIZE (type))
     201                 :     4749175 :           && tree_to_shwi (TYPE_SIZE (type)) >= 0)
     202                 :             :         size_unknown = false;
     203                 :             :       else
     204                 :             :         size_unknown = true;
     205                 :             : 
     206                 :             :       /* On a match, just return what we found.  */
     207                 :     2374599 :       if ((otr_type
     208                 :     2068264 :            && types_odr_comparable (type, otr_type)
     209                 :     2068264 :            && types_same_for_odr (type, otr_type))
     210                 :     2374599 :           || (!otr_type
     211                 :      306335 :               && TREE_CODE (type) == RECORD_TYPE
     212                 :      226833 :               && TYPE_BINFO (type)
     213                 :      226213 :               && polymorphic_type_binfo_p (TYPE_BINFO (type))))
     214                 :             :         {
     215                 :     1445971 :           if (speculative)
     216                 :             :             {
     217                 :             :               /* If we did not match the offset, just give up on speculation.  */
     218                 :        9205 :               if (cur_offset != 0
     219                 :             :                   /* Also check if speculation did not end up being same as
     220                 :             :                      non-speculation.  */
     221                 :        9205 :                   || (types_must_be_same_for_odr (speculative_outer_type,
     222                 :             :                                                   outer_type)
     223                 :          50 :                       && (maybe_derived_type
     224                 :          50 :                           == speculative_maybe_derived_type)))
     225                 :           0 :                 clear_speculation ();
     226                 :        9205 :               return true;
     227                 :             :             }
     228                 :             :           else
     229                 :             :             {
     230                 :             :               /* If type is known to be final, do not worry about derived
     231                 :             :                  types.  Testing it here may help us to avoid speculation.  */
     232                 :     1434147 :               if (otr_type && TREE_CODE (outer_type) == RECORD_TYPE
     233                 :     1434147 :                   && (!in_lto_p || odr_type_p (outer_type))
     234                 :     1434147 :                   && type_with_linkage_p (outer_type)
     235                 :     2870913 :                   && type_known_to_have_no_derivations_p (outer_type))
     236                 :        7570 :                 maybe_derived_type = false;
     237                 :             : 
     238                 :             :               /* Type cannot contain itself on an non-zero offset.  In that case
     239                 :             :                  just give up.  Still accept the case where size is now known.
     240                 :             :                  Either the second copy may appear past the end of type or within
     241                 :             :                  the non-POD buffer located inside the variably sized type
     242                 :             :                  itself.  */
     243                 :     1436766 :               if (cur_offset != 0)
     244                 :        2065 :                 goto no_useful_type_info;
     245                 :             :               /* If we determined type precisely or we have no clue on
     246                 :             :                  speculation, we are done.  */
     247                 :     1106078 :               if (!maybe_derived_type || !speculative_outer_type
     248                 :     1498918 :                   || !speculation_consistent_p (speculative_outer_type,
     249                 :             :                                                 speculative_offset,
     250                 :             :                                                 speculative_maybe_derived_type,
     251                 :             :                                                 otr_type))
     252                 :             :                 {
     253                 :     1425499 :                   clear_speculation ();
     254                 :     1425499 :                   return true;
     255                 :             :                 }
     256                 :             :               /* Otherwise look into speculation now.  */
     257                 :             :               else
     258                 :             :                 {
     259                 :        9202 :                   speculative = true;
     260                 :        9202 :                   type = speculative_outer_type;
     261                 :        9202 :                   cur_offset = speculative_offset;
     262                 :        9202 :                   continue;
     263                 :             :                 }
     264                 :             :             }
     265                 :             :         }
     266                 :             : 
     267                 :             :       /* Walk fields and find corresponding on at OFFSET.  */
     268                 :      928628 :       if (TREE_CODE (type) == RECORD_TYPE)
     269                 :             :         {
     270                 :    13346572 :           for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
     271                 :             :             {
     272                 :    24831931 :               if (TREE_CODE (fld) != FIELD_DECL
     273                 :    13103029 :                   || TREE_TYPE (fld) == error_mark_node)
     274                 :    11728902 :                 continue;
     275                 :             : 
     276                 :     1374127 :               pos = int_bit_position (fld);
     277                 :     1374127 :               if (pos > (unsigned HOST_WIDE_INT)cur_offset)
     278                 :      351820 :                 continue;
     279                 :             : 
     280                 :             :               /* Do not consider vptr itself.  Not even for placement new.  */
     281                 :      992757 :               if (!pos && DECL_ARTIFICIAL (fld)
     282                 :      801844 :                   && POINTER_TYPE_P (TREE_TYPE (fld))
     283                 :      171918 :                   && TYPE_BINFO (type)
     284                 :     1194225 :                   && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     285                 :      171918 :                 continue;
     286                 :             : 
     287                 :      850389 :               if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
     288                 :           0 :                 goto no_useful_type_info;
     289                 :      850389 :               size = tree_to_uhwi (DECL_SIZE (fld));
     290                 :             : 
     291                 :             :               /* We can always skip types smaller than pointer size:
     292                 :             :                  those cannot contain a virtual table pointer.
     293                 :             : 
     294                 :             :                  Disqualifying fields that are too small to fit OTR_TYPE
     295                 :             :                  saves work needed to walk them for no benefit.
     296                 :             :                  Because of the way the bases are packed into a class, the
     297                 :             :                  field's size may be smaller than type size, so it needs
     298                 :             :                  to be done with a care.  */
     299                 :             :                 
     300                 :      850389 :               if (pos <= (unsigned HOST_WIDE_INT)cur_offset
     301                 :     1700778 :                   && (pos + size) >= (unsigned HOST_WIDE_INT)cur_offset
     302                 :      871388 :                                      + POINTER_SIZE
     303                 :      657038 :                   && (!otr_type
     304                 :      443098 :                       || !TYPE_SIZE (TREE_TYPE (fld))
     305                 :      443098 :                       || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld)))
     306                 :      443098 :                       || (pos + tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld))))
     307                 :      443098 :                           >= cur_offset + otr_type_size))
     308                 :             :                 break;
     309                 :             :             }
     310                 :             : 
     311                 :      839148 :           if (!fld)
     312                 :      243543 :             goto no_useful_type_info;
     313                 :             : 
     314                 :      595605 :           type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
     315                 :      595605 :           cur_offset -= pos;
     316                 :             :           /* DECL_ARTIFICIAL represents a basetype.  */
     317                 :      595605 :           if (!DECL_ARTIFICIAL (fld))
     318                 :             :             {
     319                 :      197982 :               if (!speculative)
     320                 :             :                 {
     321                 :      197573 :                   outer_type = type;
     322                 :      197573 :                   offset = cur_offset;
     323                 :             :                   /* As soon as we see an field containing the type,
     324                 :             :                      we know we are not looking for derivations.  */
     325                 :      197573 :                   maybe_derived_type = false;
     326                 :             :                 }
     327                 :             :               else
     328                 :             :                 {
     329                 :         409 :                   speculative_outer_type = type;
     330                 :         409 :                   speculative_offset = cur_offset;
     331                 :         409 :                   speculative_maybe_derived_type = false;
     332                 :             :                 }
     333                 :             :             }
     334                 :      397623 :           else if (!consider_bases)
     335                 :      131990 :             goto no_useful_type_info;
     336                 :             :         }
     337                 :       89480 :       else if (TREE_CODE (type) == ARRAY_TYPE)
     338                 :             :         {
     339                 :        4248 :           tree subtype = TYPE_MAIN_VARIANT (TREE_TYPE (type));
     340                 :             : 
     341                 :             :           /* Give up if we don't know array field size.
     342                 :             :              Also give up on non-polymorphic types as they are used
     343                 :             :              as buffers for placement new.  */
     344                 :        4248 :           if (!TYPE_SIZE (subtype)
     345                 :        4248 :               || !tree_fits_shwi_p (TYPE_SIZE (subtype))
     346                 :        4248 :               || tree_to_shwi (TYPE_SIZE (subtype)) <= 0
     347                 :        8496 :               || !contains_polymorphic_type_p (subtype))
     348                 :        3864 :             goto no_useful_type_info;
     349                 :             : 
     350                 :         384 :           HOST_WIDE_INT new_offset = cur_offset % tree_to_shwi (TYPE_SIZE (subtype));
     351                 :             : 
     352                 :             :           /* We may see buffer for placement new.  In this case the expected type
     353                 :             :              can be bigger than the subtype.  */
     354                 :         384 :           if (TYPE_SIZE (subtype)
     355                 :         384 :               && (cur_offset + otr_type_size
     356                 :         384 :                   > tree_to_uhwi (TYPE_SIZE (subtype))))
     357                 :         357 :             goto no_useful_type_info;
     358                 :             : 
     359                 :          27 :           cur_offset = new_offset;
     360                 :          27 :           type = TYPE_MAIN_VARIANT (subtype);
     361                 :          27 :           if (!speculative)
     362                 :             :             {
     363                 :          27 :               outer_type = type;
     364                 :          27 :               offset = cur_offset;
     365                 :          27 :               maybe_derived_type = false;
     366                 :             :             }
     367                 :             :           else
     368                 :             :             {
     369                 :           0 :               speculative_outer_type = type;
     370                 :           0 :               speculative_offset = cur_offset;
     371                 :           0 :               speculative_maybe_derived_type = false;
     372                 :             :             }
     373                 :             :         }
     374                 :             :       /* Give up on anything else.  */
     375                 :             :       else
     376                 :             :         {
     377                 :       85232 : no_useful_type_info:
     378                 :           5 :           if (maybe_derived_type && !speculative
     379                 :           5 :               && TREE_CODE (outer_type) == RECORD_TYPE
     380                 :           5 :               && TREE_CODE (otr_type) == RECORD_TYPE
     381                 :           5 :               && TYPE_BINFO (otr_type)
     382                 :           5 :               && !offset
     383                 :      470524 :               && get_binfo_at_offset (TYPE_BINFO (otr_type), 0, outer_type))
     384                 :             :             {
     385                 :           5 :               clear_outer_type (otr_type);
     386                 :           5 :               if (!speculative_outer_type
     387                 :           5 :                   || !speculation_consistent_p (speculative_outer_type,
     388                 :             :                                                 speculative_offset,
     389                 :           0 :                                                 speculative_maybe_derived_type,
     390                 :             :                                                 otr_type))
     391                 :           5 :                 clear_speculation ();
     392                 :           5 :               if (speculative_outer_type)
     393                 :             :                 {
     394                 :           0 :                   speculative = true;
     395                 :           0 :                   type = speculative_outer_type;
     396                 :           0 :                   cur_offset = speculative_offset;
     397                 :             :                 }
     398                 :             :               else
     399                 :             :                 return true;
     400                 :             :             }
     401                 :             :           /* We found no way to embed EXPECTED_TYPE in TYPE.
     402                 :             :              We still permit two special cases - placement new and
     403                 :             :              the case of variadic types containing themselves.  */
     404                 :      470514 :           if (!speculative
     405                 :      470514 :               && consider_placement_new
     406                 :      470514 :               && (size_unknown || !type || maybe_derived_type
     407                 :      105471 :                   || possible_placement_new (type, otr_type, cur_offset)))
     408                 :             :             {
     409                 :             :               /* In these weird cases we want to accept the context.
     410                 :             :                  In non-speculative run we have no useful outer_type info
     411                 :             :                  (TODO: we may eventually want to record upper bound on the
     412                 :             :                   type size that can be used to prune the walk),
     413                 :             :                  but we still want to consider speculation that may
     414                 :             :                  give useful info.  */
     415                 :      102704 :               if (!speculative)
     416                 :             :                 {
     417                 :      102704 :                   clear_outer_type (otr_type);
     418                 :      102704 :                   if (!speculative_outer_type
     419                 :      102709 :                       || !speculation_consistent_p (speculative_outer_type,
     420                 :             :                                                     speculative_offset,
     421                 :           5 :                                                     speculative_maybe_derived_type,
     422                 :             :                                                     otr_type))
     423                 :      102701 :                     clear_speculation ();
     424                 :      102704 :                   if (speculative_outer_type)
     425                 :             :                     {
     426                 :           3 :                       speculative = true;
     427                 :           3 :                       type = speculative_outer_type;
     428                 :           3 :                       cur_offset = speculative_offset;
     429                 :             :                     }
     430                 :             :                   else
     431                 :             :                     return true;
     432                 :             :                 }
     433                 :             :               else
     434                 :             :                 {
     435                 :             :                   clear_speculation ();
     436                 :             :                   return true;
     437                 :             :                 }
     438                 :             :             }
     439                 :             :           else
     440                 :             :             {
     441                 :      367810 :               clear_speculation ();
     442                 :      367810 :               if (speculative)
     443                 :             :                 return true;
     444                 :      367810 :               clear_outer_type (otr_type);
     445                 :      367810 :               invalid = true; 
     446                 :      367810 :               return false;
     447                 :             :             }
     448                 :             :         }
     449                 :             :     }
     450                 :             : }
     451                 :             : 
     452                 :             : /* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
     453                 :             :    CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
     454                 :             :    be built within OUTER_TYPE by means of placement new.  CONSIDER_BASES makes
     455                 :             :    function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
     456                 :             :    base of one of fields of OUTER_TYPE.  */
     457                 :             : 
     458                 :             : static bool
     459                 :      660798 : contains_type_p (tree outer_type, HOST_WIDE_INT offset,
     460                 :             :                  tree otr_type,
     461                 :             :                  bool consider_placement_new,
     462                 :             :                  bool consider_bases)
     463                 :             : {
     464                 :      660798 :   ipa_polymorphic_call_context context;
     465                 :             : 
     466                 :             :   /* Check that type is within range.  */
     467                 :      660798 :   if (offset < 0)
     468                 :             :     return false;
     469                 :             : 
     470                 :             :   /* PR ipa/71207
     471                 :             :      As OUTER_TYPE can be a type which has a diamond virtual inheritance,
     472                 :             :      it's not necessary that INNER_TYPE will fit within OUTER_TYPE with
     473                 :             :      a given offset.  It can happen that INNER_TYPE also contains a base object,
     474                 :             :      however it would point to the same instance in the OUTER_TYPE.  */
     475                 :             : 
     476                 :      655140 :   context.offset = offset;
     477                 :      655140 :   context.outer_type = TYPE_MAIN_VARIANT (outer_type);
     478                 :      655140 :   context.maybe_derived_type = false;
     479                 :      655140 :   context.dynamic = false;
     480                 :      655140 :   return context.restrict_to_inner_class (otr_type, consider_placement_new,
     481                 :      655140 :                                           consider_bases);
     482                 :             : }
     483                 :             : 
     484                 :             : 
     485                 :             : /* Return a FUNCTION_DECL if FN represent a constructor or destructor.
     486                 :             :    If CHECK_CLONES is true, also check for clones of ctor/dtors.  */
     487                 :             : 
     488                 :             : tree
     489                 :    37363114 : polymorphic_ctor_dtor_p (tree fn, bool check_clones)
     490                 :             : {
     491                 :    37363114 :   if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
     492                 :    61726317 :       || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
     493                 :             :     {
     494                 :    26076735 :       if (!check_clones)
     495                 :             :         return NULL_TREE;
     496                 :             : 
     497                 :             :       /* Watch for clones where we constant propagated the first
     498                 :             :          argument (pointer to the instance).  */
     499                 :    26041235 :       fn = DECL_ABSTRACT_ORIGIN (fn);
     500                 :    26041235 :       if (!fn
     501                 :    18015623 :           || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
     502                 :    37351216 :           || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
     503                 :             :         return NULL_TREE;
     504                 :             :     }
     505                 :             : 
     506                 :    11286592 :   if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST))
     507                 :             :     return NULL_TREE;
     508                 :             : 
     509                 :             :   return fn;
     510                 :             : }
     511                 :             : 
     512                 :             : /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
     513                 :             :    If CHECK_CLONES is true, also check for clones of ctor/dtors.  */
     514                 :             : 
     515                 :             : tree
     516                 :   128655631 : inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
     517                 :             : {
     518                 :   128655631 :   tree fn = block_ultimate_origin (block);
     519                 :   128655631 :   if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
     520                 :             :     return NULL_TREE;
     521                 :             : 
     522                 :    30087917 :   return polymorphic_ctor_dtor_p (fn, check_clones);
     523                 :             : }
     524                 :             : 
     525                 :             : 
     526                 :             : /* We know that the instance is stored in variable or parameter
     527                 :             :    (not dynamically allocated) and we want to disprove the fact
     528                 :             :    that it may be in construction at invocation of CALL.
     529                 :             : 
     530                 :             :    BASE represents memory location where instance is stored.
     531                 :             :    If BASE is NULL, it is assumed to be global memory.
     532                 :             :    OUTER_TYPE is known type of the instance or NULL if not
     533                 :             :    known.
     534                 :             : 
     535                 :             :    For the variable to be in construction we actually need to
     536                 :             :    be in constructor of corresponding global variable or
     537                 :             :    the inline stack of CALL must contain the constructor.
     538                 :             :    Check this condition.  This check works safely only before
     539                 :             :    IPA passes, because inline stacks may become out of date
     540                 :             :    later.  */
     541                 :             : 
     542                 :             : bool
     543                 :    26246700 : decl_maybe_in_construction_p (tree base, tree outer_type,
     544                 :             :                               gimple *call, tree function)
     545                 :             : {
     546                 :    26246700 :   if (outer_type)
     547                 :       42429 :     outer_type = TYPE_MAIN_VARIANT (outer_type);
     548                 :    26246700 :   gcc_assert (!base || DECL_P (base));
     549                 :             : 
     550                 :             :   /* After inlining the code unification optimizations may invalidate
     551                 :             :      inline stacks.  Also we need to give up on global variables after
     552                 :             :      IPA, because addresses of these may have been propagated to their
     553                 :             :      constructors.  */
     554                 :    26246700 :   if (DECL_STRUCT_FUNCTION (function)->after_inlining)
     555                 :             :     return true;
     556                 :             : 
     557                 :             :   /* Pure functions cannot do any changes on the dynamic type;
     558                 :             :      that require writing to memory.  */
     559                 :       34127 :   if ((!base || !auto_var_in_fn_p (base, function))
     560                 :    26209835 :       && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
     561                 :             :     return false;
     562                 :             : 
     563                 :    25961286 :   bool check_clones = !base || is_global_var (base);
     564                 :   139677768 :   for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
     565                 :    56858241 :        block = BLOCK_SUPERCONTEXT (block))
     566                 :    56880345 :     if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones))
     567                 :             :       {
     568                 :      268228 :         tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
     569                 :             : 
     570                 :      268228 :         if (!outer_type || !types_odr_comparable (type, outer_type))
     571                 :             :           {
     572                 :      264441 :             if (TREE_CODE (type) == RECORD_TYPE
     573                 :      263026 :                 && TYPE_BINFO (type)
     574                 :      525213 :                 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     575                 :             :               return true;
     576                 :             :           }
     577                 :        3787 :         else if (types_same_for_odr (type, outer_type))
     578                 :             :           return true;
     579                 :             :       }
     580                 :             : 
     581                 :    25939182 :   if (!base || (VAR_P (base) && is_global_var (base)))
     582                 :             :     {
     583                 :    25911781 :       if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
     584                 :    32653232 :           || (!DECL_CXX_CONSTRUCTOR_P (function)
     585                 :     5619611 :               && !DECL_CXX_DESTRUCTOR_P (function)))
     586                 :             :         {
     587                 :    24324229 :           if (!DECL_ABSTRACT_ORIGIN (function))
     588                 :             :             return false;
     589                 :             :           /* Watch for clones where we constant propagated the first
     590                 :             :              argument (pointer to the instance).  */
     591                 :       75558 :           function = DECL_ABSTRACT_ORIGIN (function);
     592                 :       75558 :           if (!function
     593                 :       75558 :               || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
     594                 :      117325 :               || (!DECL_CXX_CONSTRUCTOR_P (function)
     595                 :       41735 :                   && !DECL_CXX_DESTRUCTOR_P (function)))
     596                 :             :             return false;
     597                 :             :         }
     598                 :     1587584 :       tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (function));
     599                 :     1587584 :       if (!outer_type || !types_odr_comparable (type, outer_type))
     600                 :             :         {
     601                 :     1587548 :           if (TREE_CODE (type) == RECORD_TYPE
     602                 :     1586389 :               && TYPE_BINFO (type)
     603                 :     3166155 :               && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     604                 :             :             return true;
     605                 :             :         }
     606                 :          36 :       else if (types_same_for_odr (type, outer_type))
     607                 :             :         return true;
     608                 :             :     }
     609                 :             :   return false;
     610                 :             : }
     611                 :             : 
     612                 :             : /* Dump human readable context to F.  If NEWLINE is true, it will be terminated
     613                 :             :    by a newline.  */
     614                 :             : 
     615                 :             : void
     616                 :        2182 : ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
     617                 :             : {
     618                 :        2182 :   fprintf (f, "    ");
     619                 :        2182 :   if (invalid)
     620                 :           0 :     fprintf (f, "Call is known to be undefined");
     621                 :             :   else
     622                 :             :     {
     623                 :        2182 :       if (useless_p ())
     624                 :         574 :         fprintf (f, "nothing known");
     625                 :        2182 :       if (outer_type || offset)
     626                 :             :         {
     627                 :        1843 :           fprintf (f, "Outer type%s:", dynamic ? " (dynamic)":"");
     628                 :        1419 :           print_generic_expr (f, outer_type, TDF_SLIM);
     629                 :        1419 :           if (maybe_derived_type)
     630                 :         773 :             fprintf (f, " (or a derived type)");
     631                 :        1419 :           if (maybe_in_construction)
     632                 :         240 :             fprintf (f, " (maybe in construction)");
     633                 :        1419 :           fprintf (f, " offset " HOST_WIDE_INT_PRINT_DEC,
     634                 :        1419 :                    offset);
     635                 :             :         }
     636                 :        2182 :       if (speculative_outer_type)
     637                 :             :         {
     638                 :         386 :           if (outer_type || offset)
     639                 :         197 :             fprintf (f, " ");
     640                 :         386 :           fprintf (f, "Speculative outer type:");
     641                 :         386 :           print_generic_expr (f, speculative_outer_type, TDF_SLIM);
     642                 :         386 :           if (speculative_maybe_derived_type)
     643                 :         351 :             fprintf (f, " (or a derived type)");
     644                 :         386 :           fprintf (f, " at offset " HOST_WIDE_INT_PRINT_DEC,
     645                 :         386 :                    speculative_offset);
     646                 :             :         }
     647                 :             :     }
     648                 :        2182 :   if (newline)
     649                 :        1356 :     fprintf(f, "\n");
     650                 :        2182 : }
     651                 :             : 
     652                 :             : /* Print context to stderr.  */
     653                 :             : 
     654                 :             : void
     655                 :           0 : ipa_polymorphic_call_context::debug () const
     656                 :             : {
     657                 :           0 :   dump (stderr);
     658                 :           0 : }
     659                 :             : 
     660                 :             : /* Stream out the context to OB.  */
     661                 :             : 
     662                 :             : void
     663                 :        2797 : ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
     664                 :             : {
     665                 :        2797 :   struct bitpack_d bp = bitpack_create (ob->main_stream);
     666                 :             : 
     667                 :        2797 :   bp_pack_value (&bp, invalid, 1);
     668                 :        2797 :   bp_pack_value (&bp, maybe_in_construction, 1);
     669                 :        2797 :   bp_pack_value (&bp, maybe_derived_type, 1);
     670                 :        2797 :   bp_pack_value (&bp, speculative_maybe_derived_type, 1);
     671                 :        2797 :   bp_pack_value (&bp, dynamic, 1);
     672                 :        2797 :   bp_pack_value (&bp, outer_type != NULL, 1);
     673                 :        2797 :   bp_pack_value (&bp, offset != 0, 1);
     674                 :        2797 :   bp_pack_value (&bp, speculative_outer_type != NULL, 1);
     675                 :        2797 :   streamer_write_bitpack (&bp);
     676                 :             : 
     677                 :        2797 :   if (outer_type != NULL)
     678                 :        1325 :     stream_write_tree (ob, outer_type, true);
     679                 :        2797 :   if (offset)
     680                 :         548 :     streamer_write_hwi (ob, offset);
     681                 :        2797 :   if (speculative_outer_type != NULL)
     682                 :             :     {
     683                 :        1015 :       stream_write_tree (ob, speculative_outer_type, true);
     684                 :        1015 :       streamer_write_hwi (ob, speculative_offset);
     685                 :             :     }
     686                 :             :   else
     687                 :        1782 :     gcc_assert (!speculative_offset);
     688                 :        2797 : }
     689                 :             : 
     690                 :             : /* Stream in the context from IB and DATA_IN.  */
     691                 :             : 
     692                 :             : void
     693                 :        1316 : ipa_polymorphic_call_context::stream_in (class lto_input_block *ib,
     694                 :             :                                          class data_in *data_in)
     695                 :             : {
     696                 :        1316 :   struct bitpack_d bp = streamer_read_bitpack (ib);
     697                 :             : 
     698                 :        1316 :   invalid = bp_unpack_value (&bp, 1);
     699                 :        1316 :   maybe_in_construction = bp_unpack_value (&bp, 1);
     700                 :        1316 :   maybe_derived_type = bp_unpack_value (&bp, 1);
     701                 :        1316 :   speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
     702                 :        1316 :   dynamic = bp_unpack_value (&bp, 1);
     703                 :        1316 :   bool outer_type_p = bp_unpack_value (&bp, 1);
     704                 :        1316 :   bool offset_p = bp_unpack_value (&bp, 1);
     705                 :        1316 :   bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
     706                 :             : 
     707                 :        1316 :   if (outer_type_p)
     708                 :         640 :     outer_type = stream_read_tree (ib, data_in);
     709                 :             :   else
     710                 :         676 :     outer_type = NULL;
     711                 :        1316 :   if (offset_p)
     712                 :         388 :     offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
     713                 :             :   else
     714                 :         928 :     offset = 0;
     715                 :        1316 :   if (speculative_outer_type_p)
     716                 :             :     {
     717                 :         500 :       speculative_outer_type = stream_read_tree (ib, data_in);
     718                 :         500 :       speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
     719                 :             :     }
     720                 :             :   else
     721                 :             :     {
     722                 :         816 :       speculative_outer_type = NULL;
     723                 :         816 :       speculative_offset = 0;
     724                 :             :     }
     725                 :        1316 : }
     726                 :             : 
     727                 :             : /* Produce polymorphic call context for call method of instance
     728                 :             :    that is located within BASE (that is assumed to be a decl) at offset OFF. */
     729                 :             : 
     730                 :             : void
     731                 :     1031389 : ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off)
     732                 :             : {
     733                 :     1031389 :   gcc_assert (DECL_P (base));
     734                 :     1031389 :   clear_speculation ();
     735                 :             : 
     736                 :     1031389 :   if (!contains_polymorphic_type_p (TREE_TYPE (base)))
     737                 :             :     {
     738                 :      988083 :       clear_outer_type ();
     739                 :      988083 :       offset = off;
     740                 :      988083 :       return;
     741                 :             :     }
     742                 :       43306 :   outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
     743                 :       43306 :   offset = off;
     744                 :             :   /* Make very conservative assumption that all objects
     745                 :             :      may be in construction. 
     746                 :             :  
     747                 :             :      It is up to caller to revisit this via
     748                 :             :      get_dynamic_type or decl_maybe_in_construction_p.  */
     749                 :       43306 :   maybe_in_construction = true;
     750                 :       43306 :   maybe_derived_type = false;
     751                 :       43306 :   dynamic = false;
     752                 :             : }
     753                 :             : 
     754                 :             : /* CST is an invariant (address of decl), try to get meaningful
     755                 :             :    polymorphic call context for polymorphic call of method 
     756                 :             :    if instance of OTR_TYPE that is located at offset OFF of this invariant.
     757                 :             :    Return FALSE if nothing meaningful can be found.  */
     758                 :             : 
     759                 :             : bool
     760                 :       10481 : ipa_polymorphic_call_context::set_by_invariant (tree cst,
     761                 :             :                                                 tree otr_type,
     762                 :             :                                                 HOST_WIDE_INT off)
     763                 :             : {
     764                 :       10481 :   poly_int64 offset2, size, max_size;
     765                 :       10481 :   bool reverse;
     766                 :       10481 :   tree base;
     767                 :             : 
     768                 :       10481 :   invalid = false;
     769                 :       10481 :   clear_outer_type (otr_type);
     770                 :             : 
     771                 :       10481 :   if (TREE_CODE (cst) != ADDR_EXPR)
     772                 :             :     return false;
     773                 :             : 
     774                 :        4157 :   cst = TREE_OPERAND (cst, 0);
     775                 :        4157 :   base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
     776                 :        4157 :   if (!DECL_P (base) || !known_size_p (max_size) || maybe_ne (max_size, size))
     777                 :             :     return false;
     778                 :             : 
     779                 :             :   /* Only type inconsistent programs can have otr_type that is
     780                 :             :      not part of outer type.  */
     781                 :        4149 :   if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type))
     782                 :             :     return false;
     783                 :             : 
     784                 :        2453 :   set_by_decl (base, off);
     785                 :        2453 :   return true;
     786                 :             : }
     787                 :             : 
     788                 :             : /* See if OP is SSA name initialized as a copy or by single assignment.
     789                 :             :    If so, walk the SSA graph up.  Because simple PHI conditional is considered
     790                 :             :    copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
     791                 :             :    graph.  */
     792                 :             : 
     793                 :             : static tree
     794                 :     5613658 : walk_ssa_copies (tree op, hash_set<tree> **global_visited = NULL)
     795                 :             : {
     796                 :     5613658 :   hash_set <tree> *visited = NULL;
     797                 :     5613658 :   STRIP_NOPS (op);
     798                 :     5613658 :   while (TREE_CODE (op) == SSA_NAME
     799                 :     2882605 :          && !SSA_NAME_IS_DEFAULT_DEF (op)
     800                 :             :          /* We might be called via fold_stmt during cfgcleanup where
     801                 :             :             SSA form need not be up-to-date.  */
     802                 :     1929024 :          && !name_registered_for_update_p (op) 
     803                 :     7881785 :          && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
     804                 :      381820 :              || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
     805                 :             :     {
     806                 :     1625991 :       if (global_visited)
     807                 :             :         {
     808                 :     1114467 :           if (!*global_visited)
     809                 :     1039409 :             *global_visited = new hash_set<tree>;
     810                 :     1114467 :           if ((*global_visited)->add (op))
     811                 :           0 :             goto done;
     812                 :             :         }       
     813                 :             :       else
     814                 :             :         {
     815                 :      511524 :           if (!visited)
     816                 :      511516 :             visited = new hash_set<tree>;
     817                 :      511524 :           if (visited->add (op))
     818                 :           0 :             goto done;
     819                 :             :         }
     820                 :             :       /* Special case
     821                 :             :          if (ptr == 0)
     822                 :             :            ptr = 0;
     823                 :             :          else
     824                 :             :            ptr = ptr.foo;
     825                 :             :          This pattern is implicitly produced for casts to non-primary
     826                 :             :          bases.  When doing context analysis, we do not really care
     827                 :             :          about the case pointer is NULL, because the call will be
     828                 :             :          undefined anyway.  */
     829                 :     1625991 :       if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
     830                 :             :         {
     831                 :       78787 :           gimple *phi = SSA_NAME_DEF_STMT (op);
     832                 :             : 
     833                 :       78787 :           if (gimple_phi_num_args (phi) > 2)
     834                 :       18473 :             goto done;
     835                 :       60314 :           if (gimple_phi_num_args (phi) == 1)
     836                 :         339 :             op = gimple_phi_arg_def (phi, 0);
     837                 :       59975 :           else if (integer_zerop (gimple_phi_arg_def (phi, 0)))
     838                 :        4808 :             op = gimple_phi_arg_def (phi, 1);
     839                 :       55167 :           else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
     840                 :        2513 :             op = gimple_phi_arg_def (phi, 0);
     841                 :             :           else
     842                 :       52654 :             goto done;
     843                 :             :         }
     844                 :             :       else
     845                 :             :         {
     846                 :     1547204 :           if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
     847                 :     1215761 :             goto done;
     848                 :      331443 :           op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
     849                 :             :         }
     850                 :      339103 :       STRIP_NOPS (op);
     851                 :             :     }
     852                 :     5613658 : done:
     853                 :     5613658 :   if (visited)
     854                 :      511516 :     delete (visited);
     855                 :     5613658 :   return op;
     856                 :             : }
     857                 :             : 
     858                 :             : /* Create polymorphic call context from IP invariant CST.
     859                 :             :    This is typically &global_var.
     860                 :             :    OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
     861                 :             :    is offset of call.  */
     862                 :             : 
     863                 :       10481 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst,
     864                 :             :                                                             tree otr_type,
     865                 :       10481 :                                                             HOST_WIDE_INT off)
     866                 :             : {
     867                 :       10481 :   clear_speculation ();
     868                 :       10481 :   set_by_invariant (cst, otr_type, off);
     869                 :       10481 : }
     870                 :             : 
     871                 :             : /* Build context for pointer REF contained in FNDECL at statement STMT.
     872                 :             :    if INSTANCE is non-NULL, return pointer to the object described by
     873                 :             :    the context or DECL where context is contained in.  */
     874                 :             : 
     875                 :     3520973 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
     876                 :             :                                                             tree ref,
     877                 :             :                                                             gimple *stmt,
     878                 :     3520973 :                                                             tree *instance)
     879                 :             : {
     880                 :     3520973 :   tree otr_type = NULL;
     881                 :     3520973 :   tree base_pointer;
     882                 :     3520973 :   hash_set <tree> *visited = NULL;
     883                 :             : 
     884                 :     3520973 :   if (TREE_CODE (ref) == OBJ_TYPE_REF)
     885                 :             :     {
     886                 :      769495 :       otr_type = obj_type_ref_class (ref);
     887                 :      769495 :       base_pointer = OBJ_TYPE_REF_OBJECT (ref);
     888                 :             :     }
     889                 :             :   else
     890                 :             :     base_pointer = ref;
     891                 :             : 
     892                 :             :   /* Set up basic info in case we find nothing interesting in the analysis.  */
     893                 :     3520973 :   clear_speculation ();
     894                 :     3520973 :   clear_outer_type (otr_type);
     895                 :     3520973 :   invalid = false;
     896                 :             : 
     897                 :             :   /* Walk SSA for outer object.  */
     898                 :     3760432 :   while (true)
     899                 :             :     {
     900                 :     3760432 :       base_pointer = walk_ssa_copies (base_pointer, &visited);
     901                 :     3760432 :       if (TREE_CODE (base_pointer) == ADDR_EXPR)
     902                 :             :         {
     903                 :     1675818 :           HOST_WIDE_INT offset2, size;
     904                 :     1675818 :           bool reverse;
     905                 :     1675818 :           tree base
     906                 :     1675818 :             = get_ref_base_and_extent_hwi (TREE_OPERAND (base_pointer, 0),
     907                 :             :                                            &offset2, &size, &reverse);
     908                 :     1675818 :           if (!base)
     909                 :             :             break;
     910                 :             : 
     911                 :     1653173 :           combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
     912                 :     1653173 :                                     offset + offset2,
     913                 :             :                                     true,
     914                 :             :                                     NULL /* Do not change outer type.  */);
     915                 :             : 
     916                 :             :           /* If this is a varying address, punt.  */
     917                 :     1653173 :           if (TREE_CODE (base) == MEM_REF || DECL_P (base))
     918                 :             :             {
     919                 :             :               /* We found dereference of a pointer.  Type of the pointer
     920                 :             :                  and MEM_REF is meaningless, but we can look further.  */
     921                 :     1268405 :               offset_int mem_offset;
     922                 :     1268405 :               if (TREE_CODE (base) == MEM_REF
     923                 :     1268405 :                   && mem_ref_offset (base).is_constant (&mem_offset))
     924                 :             :                 {
     925                 :      239469 :                   offset_int o = mem_offset * BITS_PER_UNIT;
     926                 :      239469 :                   o += offset;
     927                 :      239469 :                   o += offset2;
     928                 :      239469 :                   if (!wi::fits_shwi_p (o))
     929                 :             :                     break;
     930                 :      239459 :                   base_pointer = TREE_OPERAND (base, 0);
     931                 :      239459 :                   offset = o.to_shwi ();
     932                 :      239459 :                   outer_type = NULL;
     933                 :             :                 }
     934                 :             :               /* We found base object.  In this case the outer_type
     935                 :             :                  is known.  */
     936                 :     1028936 :               else if (DECL_P (base))
     937                 :             :                 {
     938                 :     1028936 :                   if (visited)
     939                 :         823 :                     delete (visited);
     940                 :             :                   /* Only type inconsistent programs can have otr_type that is
     941                 :             :                      not part of outer type.  */
     942                 :     1028936 :                   if (otr_type
     943                 :     1042472 :                       && !contains_type_p (TREE_TYPE (base),
     944                 :       13536 :                                            offset + offset2, otr_type))
     945                 :             :                     {
     946                 :           0 :                       invalid = true;
     947                 :           0 :                       if (instance)
     948                 :           0 :                         *instance = base_pointer;
     949                 :     1028936 :                       return;
     950                 :             :                     }
     951                 :     1028936 :                   set_by_decl (base, offset + offset2);
     952                 :     1028936 :                   if (outer_type && maybe_in_construction && stmt)
     953                 :       42429 :                     maybe_in_construction
     954                 :       42429 :                      = decl_maybe_in_construction_p (base,
     955                 :             :                                                      outer_type,
     956                 :             :                                                      stmt,
     957                 :             :                                                      fndecl);
     958                 :     1028936 :                   if (instance)
     959                 :     1019208 :                     *instance = base;
     960                 :     1028936 :                   return;
     961                 :             :                 }
     962                 :             :               else
     963                 :             :                 break;
     964                 :             :             }
     965                 :             :           else
     966                 :             :             break;
     967                 :             :         }
     968                 :     2084614 :       else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
     969                 :     2084614 :                && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
     970                 :             :         {
     971                 :           0 :           offset_int o
     972                 :           0 :             = offset_int::from (wi::to_wide (TREE_OPERAND (base_pointer, 1)),
     973                 :             :                                 SIGNED);
     974                 :           0 :           o *= BITS_PER_UNIT;
     975                 :           0 :           o += offset;
     976                 :           0 :           if (!wi::fits_shwi_p (o))
     977                 :             :             break;
     978                 :           0 :           offset = o.to_shwi ();
     979                 :           0 :           base_pointer = TREE_OPERAND (base_pointer, 0);
     980                 :             :         }
     981                 :             :       else
     982                 :             :         break;
     983                 :             :     }
     984                 :             : 
     985                 :     2492037 :   if (visited)
     986                 :     1038586 :     delete (visited);
     987                 :             : 
     988                 :             :   /* Try to determine type of the outer object.  */
     989                 :     2492037 :   if (TREE_CODE (base_pointer) == SSA_NAME
     990                 :     2015841 :       && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
     991                 :     3399463 :       && TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL)
     992                 :             :     {
     993                 :             :       /* See if parameter is THIS pointer of a method.  */
     994                 :      898710 :       if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
     995                 :     1379006 :           && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
     996                 :             :         {
     997                 :      367362 :           outer_type
     998                 :      367362 :              = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
     999                 :      367362 :           cgraph_node *node = cgraph_node::get (current_function_decl);
    1000                 :      367362 :           gcc_assert (TREE_CODE (outer_type) == RECORD_TYPE
    1001                 :             :                       || TREE_CODE (outer_type) == UNION_TYPE);
    1002                 :             : 
    1003                 :             :           /* Handle the case we inlined into a thunk.  In this case
    1004                 :             :              thunk has THIS pointer of type bar, but it really receives
    1005                 :             :              address to its base type foo which sits in bar at 
    1006                 :             :              0-thunk.fixed_offset.  It starts with code that adds
    1007                 :             :              think.fixed_offset to the pointer to compensate for this.
    1008                 :             : 
    1009                 :             :              Because we walked all the way to the beginning of thunk, we now
    1010                 :             :              see pointer &bar-thunk.fixed_offset and need to compensate
    1011                 :             :              for it.  */
    1012                 :      367362 :           thunk_info *info = thunk_info::get (node);
    1013                 :      367362 :           if (info && info->fixed_offset)
    1014                 :           7 :             offset -= info->fixed_offset * BITS_PER_UNIT;
    1015                 :             : 
    1016                 :             :           /* Dynamic casting has possibly upcasted the type
    1017                 :             :              in the hierarchy.  In this case outer type is less
    1018                 :             :              informative than inner type and we should forget
    1019                 :             :              about it.  */
    1020                 :      367362 :           if ((otr_type
    1021                 :      139510 :                && !contains_type_p (outer_type, offset,
    1022                 :             :                                     otr_type))
    1023                 :      367255 :               || !contains_polymorphic_type_p (outer_type)
    1024                 :             :               /* If we compile thunk with virtual offset, the THIS pointer
    1025                 :             :                  is adjusted by unknown value.  We can't thus use outer info
    1026                 :             :                  at all.  */
    1027                 :      564113 :               || (info && info->virtual_offset_p))
    1028                 :             :             {
    1029                 :      170611 :               outer_type = NULL;
    1030                 :      170611 :               if (instance)
    1031                 :      170370 :                 *instance = base_pointer;
    1032                 :      170611 :               return;
    1033                 :             :             }
    1034                 :             : 
    1035                 :      196751 :           dynamic = true;
    1036                 :             : 
    1037                 :             :           /* If the function is constructor or destructor, then
    1038                 :             :              the type is possibly in construction, but we know
    1039                 :             :              it is not derived type.  */
    1040                 :      196751 :           if (DECL_CXX_CONSTRUCTOR_P (fndecl)
    1041                 :      196751 :               || DECL_CXX_DESTRUCTOR_P (fndecl))
    1042                 :             :             {
    1043                 :       31774 :               maybe_in_construction = true;
    1044                 :       31774 :               maybe_derived_type = false;
    1045                 :             :             }
    1046                 :             :           else
    1047                 :             :             {
    1048                 :      164977 :               maybe_derived_type = true;
    1049                 :      164977 :               maybe_in_construction = false;
    1050                 :             :             }
    1051                 :      196751 :           if (instance)
    1052                 :             :             {
    1053                 :       93215 :               thunk_info *info = thunk_info::get (node);
    1054                 :             :               /* If method is expanded thunk, we need to apply thunk offset
    1055                 :             :                  to instance pointer.  */
    1056                 :       93215 :               if (info && (info->virtual_offset_p || info->fixed_offset))
    1057                 :           5 :                 *instance = NULL;
    1058                 :             :               else
    1059                 :       93210 :                 *instance = base_pointer;
    1060                 :             :             }
    1061                 :      196751 :           return;
    1062                 :             :         }
    1063                 :             :       /* Non-PODs passed by value are really passed by invisible
    1064                 :             :          reference.  In this case we also know the type of the
    1065                 :             :          object.  */
    1066                 :      531348 :       if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
    1067                 :             :         {
    1068                 :       14167 :           outer_type
    1069                 :       14167 :              = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
    1070                 :             :           /* Only type inconsistent programs can have otr_type that is
    1071                 :             :              not part of outer type.  */
    1072                 :       14167 :           if (otr_type && !contains_type_p (outer_type, offset,
    1073                 :             :                                             otr_type))
    1074                 :             :             { 
    1075                 :           0 :               invalid = true;
    1076                 :           0 :               if (instance)
    1077                 :           0 :                 *instance = base_pointer;
    1078                 :           0 :               return;
    1079                 :             :             }
    1080                 :             :           /* Non-polymorphic types have no interest for us.  */
    1081                 :       14167 :           else if (!otr_type && !contains_polymorphic_type_p (outer_type))
    1082                 :             :             {
    1083                 :       14079 :               outer_type = NULL;
    1084                 :       14079 :               if (instance)
    1085                 :       14079 :                 *instance = base_pointer;
    1086                 :       14079 :               return;
    1087                 :             :             }
    1088                 :          88 :           maybe_derived_type = false;
    1089                 :          88 :           maybe_in_construction = false;
    1090                 :          88 :           if (instance)
    1091                 :          69 :             *instance = base_pointer;
    1092                 :          88 :           return;
    1093                 :             :         }
    1094                 :             :     }
    1095                 :             : 
    1096                 :     2110508 :   tree base_type = TREE_TYPE (base_pointer);
    1097                 :             : 
    1098                 :     2110508 :   if (TREE_CODE (base_pointer) == SSA_NAME
    1099                 :     1634312 :       && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
    1100                 :     2636405 :       && !(TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL
    1101                 :        8716 :            || TREE_CODE (SSA_NAME_VAR (base_pointer)) == RESULT_DECL))
    1102                 :             :     {
    1103                 :         324 :       invalid = true;
    1104                 :         324 :       if (instance)
    1105                 :         178 :         *instance = base_pointer;
    1106                 :         324 :       return;
    1107                 :             :     }
    1108                 :     2110184 :   if (TREE_CODE (base_pointer) == SSA_NAME
    1109                 :     1633988 :       && SSA_NAME_DEF_STMT (base_pointer)
    1110                 :     3744172 :       && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer)))
    1111                 :      758837 :     base_type = TREE_TYPE (gimple_assign_rhs1
    1112                 :             :                             (SSA_NAME_DEF_STMT (base_pointer)));
    1113                 :             :  
    1114                 :     2110184 :   if (base_type && POINTER_TYPE_P (base_type))
    1115                 :     2110184 :     combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)),
    1116                 :             :                               offset,
    1117                 :             :                               true, NULL /* Do not change type here */);
    1118                 :             :   /* TODO: There are multiple ways to derive a type.  For instance
    1119                 :             :      if BASE_POINTER is passed to an constructor call prior our reference.
    1120                 :             :      We do not make this type of flow sensitive analysis yet.  */
    1121                 :     2110184 :   if (instance)
    1122                 :     1647901 :     *instance = base_pointer;
    1123                 :             :   return;
    1124                 :             : }
    1125                 :             : 
    1126                 :             : /* Structure to be passed in between detect_type_change and
    1127                 :             :    check_stmt_for_type_change.  */
    1128                 :             : 
    1129                 :             : struct type_change_info
    1130                 :             : {
    1131                 :             :   /* Offset into the object where there is the virtual method pointer we are
    1132                 :             :      looking for.  */
    1133                 :             :   HOST_WIDE_INT offset;
    1134                 :             :   /* The declaration or SSA_NAME pointer of the base that we are checking for
    1135                 :             :      type change.  */
    1136                 :             :   tree instance;
    1137                 :             :   /* The reference to virtual table pointer used.  */
    1138                 :             :   tree vtbl_ptr_ref;
    1139                 :             :   tree otr_type;
    1140                 :             :   /* If we actually can tell the type that the object has changed to, it is
    1141                 :             :      stored in this field.  Otherwise it remains NULL_TREE.  */
    1142                 :             :   tree known_current_type;
    1143                 :             :   HOST_WIDE_INT known_current_offset;
    1144                 :             : 
    1145                 :             :   /* Set to nonzero if we possibly missed some dynamic type changes and we
    1146                 :             :      should consider the set to be speculative.  */
    1147                 :             :   unsigned speculative;
    1148                 :             : 
    1149                 :             :   /* Set to true if dynamic type change has been detected.  */
    1150                 :             :   bool type_maybe_changed;
    1151                 :             :   /* Set to true if multiple types have been encountered.  known_current_type
    1152                 :             :      must be disregarded in that case.  */
    1153                 :             :   bool multiple_types_encountered;
    1154                 :             :   bool seen_unanalyzed_store;
    1155                 :             : };
    1156                 :             : 
    1157                 :             : /* Return true if STMT is not call and can modify a virtual method table pointer.
    1158                 :             :    We take advantage of fact that vtable stores must appear within constructor
    1159                 :             :    and destructor functions.  */
    1160                 :             : 
    1161                 :             : static bool
    1162                 :     5978491 : noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
    1163                 :             : {
    1164                 :     5978491 :   if (is_gimple_assign (stmt))
    1165                 :             :     {
    1166                 :     5887187 :       tree lhs = gimple_assign_lhs (stmt);
    1167                 :             : 
    1168                 :     5887187 :       if (gimple_clobber_p (stmt))
    1169                 :             :         return false;
    1170                 :     4923177 :       if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
    1171                 :             :         {
    1172                 :     4315304 :           if (flag_strict_aliasing
    1173                 :     4315304 :               && !POINTER_TYPE_P (TREE_TYPE (lhs)))
    1174                 :             :             return false;
    1175                 :             : 
    1176                 :     2158826 :           if (TREE_CODE (lhs) == COMPONENT_REF
    1177                 :     2158826 :               && !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
    1178                 :             :             return false;
    1179                 :             :           /* In the future we might want to use get_ref_base_and_extent to find
    1180                 :             :              if there is a field corresponding to the offset and if so, proceed
    1181                 :             :              almost like if it was a component ref.  */
    1182                 :             :         }
    1183                 :             :     }
    1184                 :             : 
    1185                 :             :   /* Code unification may mess with inline stacks.  */
    1186                 :     1112139 :   if (cfun->after_inlining)
    1187                 :             :     return true;
    1188                 :             : 
    1189                 :             :   /* Walk the inline stack and watch out for ctors/dtors.
    1190                 :             :      TODO: Maybe we can require the store to appear in toplevel
    1191                 :             :      block of CTOR/DTOR.  */
    1192                 :     9468285 :   for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK;
    1193                 :     4189064 :        block = BLOCK_SUPERCONTEXT (block))
    1194                 :     4229482 :     if (BLOCK_ABSTRACT_ORIGIN (block)
    1195                 :     4229482 :         && TREE_CODE (block_ultimate_origin (block)) == FUNCTION_DECL)
    1196                 :       40418 :       return inlined_polymorphic_ctor_dtor_block_p (block, false);
    1197                 :     1049739 :   return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
    1198                 :     1049739 :           && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
    1199                 :       61083 :               || DECL_CXX_DESTRUCTOR_P (current_function_decl)));
    1200                 :             : }
    1201                 :             : 
    1202                 :             : /* If STMT can be proved to be an assignment to the virtual method table
    1203                 :             :    pointer of ANALYZED_OBJ and the type associated with the new table
    1204                 :             :    identified, return the type.  Otherwise return NULL_TREE if type changes
    1205                 :             :    in unknown way or ERROR_MARK_NODE if type is unchanged.  */
    1206                 :             : 
    1207                 :             : static tree
    1208                 :       49505 : extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
    1209                 :             :                                HOST_WIDE_INT *type_offset)
    1210                 :             : {
    1211                 :       49505 :   poly_int64 offset, size, max_size;
    1212                 :       49505 :   tree lhs, rhs, base;
    1213                 :       49505 :   bool reverse;
    1214                 :             : 
    1215                 :       49505 :   if (!gimple_assign_single_p (stmt))
    1216                 :             :     return NULL_TREE;
    1217                 :             : 
    1218                 :       49073 :   lhs = gimple_assign_lhs (stmt);
    1219                 :       49073 :   rhs = gimple_assign_rhs1 (stmt);
    1220                 :       49073 :   if (TREE_CODE (lhs) != COMPONENT_REF
    1221                 :       49073 :       || !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
    1222                 :             :      {
    1223                 :       12230 :         if (dump_file)
    1224                 :           0 :           fprintf (dump_file, "  LHS is not virtual table.\n");
    1225                 :       12230 :         return NULL_TREE;
    1226                 :             :      }
    1227                 :             : 
    1228                 :       36843 :   if (tci->vtbl_ptr_ref && operand_equal_p (lhs, tci->vtbl_ptr_ref, 0))
    1229                 :             :     ;
    1230                 :             :   else
    1231                 :             :     {
    1232                 :       36750 :       base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
    1233                 :       36750 :       if (DECL_P (tci->instance))
    1234                 :             :         {
    1235                 :        1507 :           if (base != tci->instance)
    1236                 :             :             {
    1237                 :          13 :               if (dump_file)
    1238                 :             :                 {
    1239                 :           0 :                   fprintf (dump_file, "    base:");
    1240                 :           0 :                   print_generic_expr (dump_file, base, TDF_SLIM);
    1241                 :           0 :                   fprintf (dump_file, " does not match instance:");
    1242                 :           0 :                   print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1243                 :           0 :                   fprintf (dump_file, "\n");
    1244                 :             :                 }
    1245                 :          13 :               return NULL_TREE;
    1246                 :             :             }
    1247                 :             :         }
    1248                 :       35243 :       else if (TREE_CODE (base) == MEM_REF)
    1249                 :             :         {
    1250                 :       26668 :           if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
    1251                 :             :             {
    1252                 :       15207 :               if (dump_file)
    1253                 :             :                 {
    1254                 :           0 :                   fprintf (dump_file, "    base mem ref:");
    1255                 :           0 :                   print_generic_expr (dump_file, base, TDF_SLIM);
    1256                 :           0 :                   fprintf (dump_file, " does not match instance:");
    1257                 :           0 :                   print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1258                 :           0 :                   fprintf (dump_file, "\n");
    1259                 :             :                 }
    1260                 :       15207 :               return NULL_TREE;
    1261                 :             :             }
    1262                 :       11461 :           if (!integer_zerop (TREE_OPERAND (base, 1)))
    1263                 :             :             {
    1264                 :        1357 :               if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
    1265                 :             :                 {
    1266                 :           0 :                   if (dump_file)
    1267                 :             :                     {
    1268                 :           0 :                       fprintf (dump_file, "    base mem ref:");
    1269                 :           0 :                       print_generic_expr (dump_file, base, TDF_SLIM);
    1270                 :           0 :                       fprintf (dump_file, " has non-representable offset:");
    1271                 :           0 :                       print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1272                 :           0 :                       fprintf (dump_file, "\n");
    1273                 :             :                     }
    1274                 :           0 :                   return NULL_TREE;
    1275                 :             :                 }
    1276                 :             :               else
    1277                 :        1357 :                 offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
    1278                 :             :             }
    1279                 :             :         }
    1280                 :        8575 :       else if (!operand_equal_p (tci->instance, base, 0)
    1281                 :        8575 :                || tci->offset)
    1282                 :             :         {
    1283                 :        8575 :           if (dump_file)
    1284                 :             :             {
    1285                 :           2 :               fprintf (dump_file, "    base:");
    1286                 :           2 :               print_generic_expr (dump_file, base, TDF_SLIM);
    1287                 :           2 :               fprintf (dump_file, " does not match instance:");
    1288                 :           2 :               print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1289                 :           2 :               fprintf (dump_file, " with offset %i\n", (int)tci->offset);
    1290                 :             :             }
    1291                 :        8625 :           return tci->offset > POINTER_SIZE ? error_mark_node : NULL_TREE;
    1292                 :             :         }
    1293                 :       12955 :       if (maybe_ne (offset, tci->offset)
    1294                 :       13352 :           || maybe_ne (size, POINTER_SIZE)
    1295                 :       26307 :           || maybe_ne (max_size, POINTER_SIZE))
    1296                 :             :         {
    1297                 :          36 :           if (dump_file)
    1298                 :             :             {
    1299                 :           0 :               fprintf (dump_file, "    wrong offset ");
    1300                 :           0 :               print_dec (offset, dump_file);
    1301                 :           0 :               fprintf (dump_file, "!=%i or size ", (int) tci->offset);
    1302                 :           0 :               print_dec (size, dump_file);
    1303                 :           0 :               fprintf (dump_file, "\n");
    1304                 :             :             }
    1305                 :          36 :           return (known_le (offset + POINTER_SIZE, tci->offset)
    1306                 :           0 :                   || (known_size_p (max_size)
    1307                 :           0 :                       && known_gt (tci->offset + POINTER_SIZE,
    1308                 :             :                                    offset + max_size))
    1309                 :          36 :                   ? error_mark_node : NULL);
    1310                 :             :         }
    1311                 :             :     }
    1312                 :             : 
    1313                 :       13012 :   tree vtable;
    1314                 :       13012 :   unsigned HOST_WIDE_INT offset2;
    1315                 :             : 
    1316                 :       13012 :   if (!vtable_pointer_value_to_vtable (rhs, &vtable, &offset2))
    1317                 :             :     {
    1318                 :          71 :       if (dump_file)
    1319                 :           5 :         fprintf (dump_file, "    Failed to lookup binfo\n");
    1320                 :          71 :       return NULL;
    1321                 :             :     }
    1322                 :             : 
    1323                 :       12941 :   tree binfo = subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
    1324                 :             :                                                offset2, vtable);
    1325                 :       12941 :   if (!binfo)
    1326                 :             :     {
    1327                 :         189 :       if (dump_file)
    1328                 :          17 :         fprintf (dump_file, "    Construction vtable used\n");
    1329                 :             :       /* FIXME: We should support construction contexts.  */
    1330                 :         189 :       return NULL;
    1331                 :             :     }
    1332                 :             :  
    1333                 :       12752 :   *type_offset = tree_to_shwi (BINFO_OFFSET (binfo)) * BITS_PER_UNIT;
    1334                 :       12752 :   return DECL_CONTEXT (vtable);
    1335                 :             : }
    1336                 :             : 
    1337                 :             : /* Record dynamic type change of TCI to TYPE.  */
    1338                 :             : 
    1339                 :             : static void
    1340                 :      111741 : record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
    1341                 :             : {
    1342                 :      111741 :   if (dump_file)
    1343                 :             :     {
    1344                 :          51 :       if (type)
    1345                 :             :         {
    1346                 :          51 :           fprintf (dump_file, "  Recording type: ");
    1347                 :          51 :           print_generic_expr (dump_file, type, TDF_SLIM);
    1348                 :          51 :           fprintf (dump_file, " at offset %i\n", (int)offset);
    1349                 :             :         }
    1350                 :             :      else
    1351                 :           0 :        fprintf (dump_file, "  Recording unknown type\n");
    1352                 :             :     }
    1353                 :             : 
    1354                 :             :   /* If we found a constructor of type that is not polymorphic or
    1355                 :             :      that may contain the type in question as a field (not as base),
    1356                 :             :      restrict to the inner class first to make type matching bellow
    1357                 :             :      happier.  */
    1358                 :      111741 :   if (type
    1359                 :      111741 :       && (offset
    1360                 :      106187 :           || (TREE_CODE (type) != RECORD_TYPE
    1361                 :      106187 :               || !TYPE_BINFO (type)
    1362                 :      105791 :               || !polymorphic_type_binfo_p (TYPE_BINFO (type)))))
    1363                 :             :     {
    1364                 :       95876 :       ipa_polymorphic_call_context context;
    1365                 :             : 
    1366                 :       95876 :       context.offset = offset;
    1367                 :       95876 :       context.outer_type = type;
    1368                 :       95876 :       context.maybe_in_construction = false;
    1369                 :       95876 :       context.maybe_derived_type = false;
    1370                 :       95876 :       context.dynamic = true;
    1371                 :             :       /* If we failed to find the inner type, we know that the call
    1372                 :             :          would be undefined for type produced here.  */
    1373                 :       95876 :       if (!context.restrict_to_inner_class (tci->otr_type))
    1374                 :             :         {
    1375                 :         876 :           if (dump_file)
    1376                 :           0 :             fprintf (dump_file, "  Ignoring; does not contain otr_type\n");
    1377                 :         876 :           return;
    1378                 :             :         }
    1379                 :             :       /* Watch for case we reached an POD type and anticipate placement
    1380                 :             :          new.  */
    1381                 :       95000 :       if (!context.maybe_derived_type)
    1382                 :             :         {
    1383                 :         575 :           type = context.outer_type;
    1384                 :         575 :           offset = context.offset;
    1385                 :             :         }
    1386                 :             :     }
    1387                 :      110865 :   if (tci->type_maybe_changed
    1388                 :      110865 :       && (!types_same_for_odr (type, tci->known_current_type)
    1389                 :          21 :           || offset != tci->known_current_offset))
    1390                 :           2 :     tci->multiple_types_encountered = true;
    1391                 :      110865 :   tci->known_current_type = TYPE_MAIN_VARIANT (type);
    1392                 :      110865 :   tci->known_current_offset = offset;
    1393                 :      110865 :   tci->type_maybe_changed = true;
    1394                 :             : }
    1395                 :             : 
    1396                 :             : 
    1397                 :             : /* The maximum number of may-defs we visit when looking for a must-def
    1398                 :             :    that changes the dynamic type in check_stmt_for_type_change.  Tuned
    1399                 :             :    after the PR12392 testcase which unlimited spends 40% time within
    1400                 :             :    these alias walks and 8% with the following limit.  */
    1401                 :             : 
    1402                 :             : static inline bool
    1403                 :    13430112 : csftc_abort_walking_p (unsigned speculative)
    1404                 :             : {
    1405                 :    13430112 :   unsigned max = param_max_speculative_devirt_maydefs;
    1406                 :    13430112 :   return speculative > max ? true : false;
    1407                 :             : }
    1408                 :             : 
    1409                 :             : /* Callback of walk_aliased_vdefs and a helper function for
    1410                 :             :    detect_type_change to check whether a particular statement may modify
    1411                 :             :    the virtual table pointer, and if possible also determine the new type of
    1412                 :             :    the (sub-)object.  It stores its result into DATA, which points to a
    1413                 :             :    type_change_info structure.  */
    1414                 :             : 
    1415                 :             : static bool
    1416                 :    19510796 : check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
    1417                 :             : {
    1418                 :    19510796 :   gimple *stmt = SSA_NAME_DEF_STMT (vdef);
    1419                 :    19510796 :   struct type_change_info *tci = (struct type_change_info *) data;
    1420                 :    19510796 :   tree fn;
    1421                 :             : 
    1422                 :             :   /* If we already gave up, just terminate the rest of walk.  */
    1423                 :    19510796 :   if (tci->multiple_types_encountered)
    1424                 :             :     return true;
    1425                 :             : 
    1426                 :    19510796 :   if (is_gimple_call (stmt))
    1427                 :             :     {
    1428                 :    13532305 :       if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
    1429                 :             :         return false;
    1430                 :             : 
    1431                 :             :       /* Check for a constructor call.  */
    1432                 :    13529101 :       if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
    1433                 :    12239398 :           && DECL_CXX_CONSTRUCTOR_P (fn)
    1434                 :      708058 :           && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
    1435                 :    14237159 :           && gimple_call_num_args (stmt))
    1436                 :             :       {
    1437                 :      708058 :         tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
    1438                 :      708058 :         tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
    1439                 :      708058 :         HOST_WIDE_INT offset = 0;
    1440                 :      708058 :         bool reverse;
    1441                 :             : 
    1442                 :      708058 :         if (dump_file)
    1443                 :             :           {
    1444                 :          37 :             fprintf (dump_file, "  Checking constructor call: ");
    1445                 :          37 :             print_gimple_stmt (dump_file, stmt, 0);
    1446                 :             :           }
    1447                 :             : 
    1448                 :             :         /* See if THIS parameter seems like instance pointer.  */
    1449                 :      708058 :         if (TREE_CODE (op) == ADDR_EXPR)
    1450                 :             :           {
    1451                 :      687780 :             HOST_WIDE_INT size;
    1452                 :      687780 :             op = get_ref_base_and_extent_hwi (TREE_OPERAND (op, 0),
    1453                 :             :                                               &offset, &size, &reverse);
    1454                 :      687780 :             if (!op)
    1455                 :             :               {
    1456                 :           0 :                 tci->speculative++;
    1457                 :           0 :                 return csftc_abort_walking_p (tci->speculative);
    1458                 :             :               }
    1459                 :      687780 :             if (TREE_CODE (op) == MEM_REF)
    1460                 :             :               {
    1461                 :       50148 :                 if (!tree_fits_shwi_p (TREE_OPERAND (op, 1)))
    1462                 :             :                   {
    1463                 :           0 :                     tci->speculative++;
    1464                 :           0 :                     return csftc_abort_walking_p (tci->speculative);
    1465                 :             :                   }
    1466                 :       50148 :                 offset += tree_to_shwi (TREE_OPERAND (op, 1))
    1467                 :       50148 :                           * BITS_PER_UNIT;
    1468                 :       50148 :                 op = TREE_OPERAND (op, 0);
    1469                 :             :               }
    1470                 :      637632 :             else if (DECL_P (op))
    1471                 :             :               ;
    1472                 :             :             else
    1473                 :             :               {
    1474                 :           0 :                 tci->speculative++;
    1475                 :           0 :                 return csftc_abort_walking_p (tci->speculative);
    1476                 :             :               }
    1477                 :      687780 :             op = walk_ssa_copies (op);
    1478                 :             :           }
    1479                 :      708058 :         if (operand_equal_p (op, tci->instance, 0)
    1480                 :      148998 :             && TYPE_SIZE (type)
    1481                 :      148998 :             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
    1482                 :      148998 :             && tree_fits_shwi_p (TYPE_SIZE (type))
    1483                 :      148998 :             && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset
    1484                 :             :             /* Some inlined constructors may look as follows:
    1485                 :             :                   _3 = operator new (16);
    1486                 :             :                   MEM[(struct  &)_3] ={v} {CLOBBER};
    1487                 :             :                   MEM[(struct CompositeClass *)_3]._vptr.CompositeClass
    1488                 :             :                     = &MEM[(void *)&_ZTV14CompositeClass + 16B];
    1489                 :             :                   _7 = &MEM[(struct CompositeClass *)_3].object;
    1490                 :             :                   EmptyClass::EmptyClass (_7);
    1491                 :             : 
    1492                 :             :                When determining dynamic type of _3 and because we stop at first
    1493                 :             :                dynamic type found, we would stop on EmptyClass::EmptyClass (_7).
    1494                 :             :                In this case the emptyclass is not even polymorphic and we miss
    1495                 :             :                it is contained in an outer type that is polymorphic.  */
    1496                 :             : 
    1497                 :      825903 :             && (tci->offset == offset || contains_polymorphic_type_p (type)))
    1498                 :             :           {
    1499                 :       98989 :             record_known_type (tci, type, tci->offset - offset);
    1500                 :       98989 :             return true;
    1501                 :             :           }
    1502                 :             :       }
    1503                 :             :      /* Calls may possibly change dynamic type by placement new. Assume
    1504                 :             :         it will not happen, but make result speculative only.  */
    1505                 :    13430112 :      if (dump_file)
    1506                 :             :         {
    1507                 :         882 :           fprintf (dump_file, "  Function call may change dynamic type:");
    1508                 :         882 :           print_gimple_stmt (dump_file, stmt, 0);
    1509                 :             :         }
    1510                 :    13430112 :      tci->speculative++;
    1511                 :    13430112 :      return csftc_abort_walking_p (tci->speculative);
    1512                 :             :    }
    1513                 :             :   /* Check for inlined virtual table store.  */
    1514                 :     5978491 :   else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
    1515                 :             :     {
    1516                 :       49505 :       tree type;
    1517                 :       49505 :       HOST_WIDE_INT offset = 0;
    1518                 :       49505 :       if (dump_file)
    1519                 :             :         {
    1520                 :          51 :           fprintf (dump_file, "  Checking vtbl store: ");
    1521                 :          51 :           print_gimple_stmt (dump_file, stmt, 0);
    1522                 :             :         }
    1523                 :             : 
    1524                 :       49505 :       type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
    1525                 :       49505 :       if (type == error_mark_node)
    1526                 :             :         return false;
    1527                 :       49469 :       gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
    1528                 :       49469 :       if (!type)
    1529                 :             :         {
    1530                 :       36717 :           if (dump_file)
    1531                 :          24 :             fprintf (dump_file, "  Unanalyzed store may change type.\n");
    1532                 :       36717 :           tci->seen_unanalyzed_store = true;
    1533                 :       36717 :           tci->speculative++;
    1534                 :             :         }
    1535                 :             :       else
    1536                 :       12752 :         record_known_type (tci, type, offset);
    1537                 :       49469 :       return true;
    1538                 :             :     }
    1539                 :             :   else
    1540                 :             :     return false;
    1541                 :             : }
    1542                 :             : 
    1543                 :             : /* THIS is polymorphic call context obtained from get_polymorphic_context.
    1544                 :             :    OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
    1545                 :             :    INSTANCE is pointer to the outer instance as returned by
    1546                 :             :    get_polymorphic_context.  To avoid creation of temporary expressions,
    1547                 :             :    INSTANCE may also be an declaration of get_polymorphic_context found the
    1548                 :             :    value to be in static storage.
    1549                 :             : 
    1550                 :             :    If the type of instance is not fully determined
    1551                 :             :    (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
    1552                 :             :    is set), try to walk memory writes and find the actual construction of the
    1553                 :             :    instance.
    1554                 :             : 
    1555                 :             :    Return true if memory is unchanged from function entry.
    1556                 :             : 
    1557                 :             :    We do not include this analysis in the context analysis itself, because
    1558                 :             :    it needs memory SSA to be fully built and the walk may be expensive.
    1559                 :             :    So it is not suitable for use withing fold_stmt and similar uses.
    1560                 :             : 
    1561                 :             :    AA_WALK_BUDGET_P, if not NULL, is how statements we should allow
    1562                 :             :    walk_aliased_vdefs to examine.  The value should be decremented by the
    1563                 :             :    number of statements we examined or set to zero if exhausted.  */
    1564                 :             : 
    1565                 :             : bool
    1566                 :     2945020 : ipa_polymorphic_call_context::get_dynamic_type (tree instance,
    1567                 :             :                                                 tree otr_object,
    1568                 :             :                                                 tree otr_type,
    1569                 :             :                                                 gimple *call,
    1570                 :             :                                                 unsigned *aa_walk_budget_p)
    1571                 :             : {
    1572                 :     2945020 :   struct type_change_info tci;
    1573                 :     2945020 :   ao_ref ao;
    1574                 :     2945020 :   bool function_entry_reached = false;
    1575                 :     2945020 :   tree instance_ref = NULL;
    1576                 :     2945020 :   gimple *stmt = call;
    1577                 :             :   /* Remember OFFSET before it is modified by restrict_to_inner_class.
    1578                 :             :      This is because we do not update INSTANCE when walking inwards.  */
    1579                 :     2945020 :   HOST_WIDE_INT instance_offset = offset;
    1580                 :     2945020 :   tree instance_outer_type = outer_type;
    1581                 :             : 
    1582                 :     2945020 :   if (!instance)
    1583                 :             :     return false;
    1584                 :             : 
    1585                 :     2945015 :   if (otr_type)
    1586                 :      193542 :     otr_type = TYPE_MAIN_VARIANT (otr_type);
    1587                 :             : 
    1588                 :             :   /* Walk into inner type. This may clear maybe_derived_type and save us
    1589                 :             :      from useless work.  It also makes later comparisons with static type
    1590                 :             :      easier.  */
    1591                 :     2945015 :   if (outer_type && otr_type)
    1592                 :             :     {
    1593                 :      171941 :       if (!restrict_to_inner_class (otr_type))
    1594                 :             :         return false;
    1595                 :             :     }
    1596                 :             : 
    1597                 :     2945015 :   if (!maybe_in_construction && !maybe_derived_type)
    1598                 :             :     return false;
    1599                 :             : 
    1600                 :             :   /* If we are in fact not looking at any object or the instance is
    1601                 :             :      some placement new into a random load, give up straight away.  */
    1602                 :     2917249 :   if (TREE_CODE (instance) == MEM_REF)
    1603                 :             :     return false;
    1604                 :             : 
    1605                 :             :   /* We need to obtain reference to virtual table pointer.  It is better
    1606                 :             :      to look it up in the code rather than build our own.  This require bit
    1607                 :             :      of pattern matching, but we end up verifying that what we found is
    1608                 :             :      correct. 
    1609                 :             : 
    1610                 :             :      What we pattern match is:
    1611                 :             : 
    1612                 :             :        tmp = instance->_vptr.A;   // vtbl ptr load
    1613                 :             :        tmp2 = tmp[otr_token];     // vtable lookup
    1614                 :             :        OBJ_TYPE_REF(tmp2;instance->0) (instance);
    1615                 :             :  
    1616                 :             :      We want to start alias oracle walk from vtbl pointer load,
    1617                 :             :      but we may not be able to identify it, for example, when PRE moved the
    1618                 :             :      load around.  */
    1619                 :             : 
    1620                 :     2917249 :   if (gimple_code (call) == GIMPLE_CALL)
    1621                 :             :     {
    1622                 :     2917249 :       tree ref = gimple_call_fn (call);
    1623                 :     2917249 :       bool reverse;
    1624                 :             : 
    1625                 :     2917249 :       if (TREE_CODE (ref) == OBJ_TYPE_REF)
    1626                 :             :         {
    1627                 :      228744 :           ref = OBJ_TYPE_REF_EXPR (ref);
    1628                 :      228744 :           ref = walk_ssa_copies (ref);
    1629                 :             : 
    1630                 :             :           /* If call target is already known, no need to do the expensive
    1631                 :             :              memory walk.  */
    1632                 :      228744 :           if (is_gimple_min_invariant (ref))
    1633                 :           0 :             return false;
    1634                 :             : 
    1635                 :             :           /* Check if definition looks like vtable lookup.  */
    1636                 :      228744 :           if (TREE_CODE (ref) == SSA_NAME
    1637                 :      228744 :               && !SSA_NAME_IS_DEFAULT_DEF (ref)
    1638                 :      228744 :               && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))
    1639                 :      457408 :               && TREE_CODE (gimple_assign_rhs1
    1640                 :             :                              (SSA_NAME_DEF_STMT (ref))) == MEM_REF)
    1641                 :             :             {
    1642                 :      228644 :               ref = get_base_address
    1643                 :      228644 :                      (TREE_OPERAND (gimple_assign_rhs1
    1644                 :             :                                      (SSA_NAME_DEF_STMT (ref)), 0));
    1645                 :      228644 :               ref = walk_ssa_copies (ref);
    1646                 :             :               /* Find base address of the lookup and see if it looks like
    1647                 :             :                  vptr load.  */
    1648                 :      228644 :               if (TREE_CODE (ref) == SSA_NAME
    1649                 :      228491 :                   && !SSA_NAME_IS_DEFAULT_DEF (ref)
    1650                 :      457135 :                   && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
    1651                 :             :                 {
    1652                 :      227985 :                   HOST_WIDE_INT offset2, size;
    1653                 :      227985 :                   tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
    1654                 :      227985 :                   tree base_ref
    1655                 :      227985 :                     = get_ref_base_and_extent_hwi (ref_exp, &offset2,
    1656                 :             :                                                    &size, &reverse);
    1657                 :             : 
    1658                 :             :                   /* Finally verify that what we found looks like read from
    1659                 :             :                      OTR_OBJECT or from INSTANCE with offset OFFSET.  */
    1660                 :      227985 :                   if (base_ref
    1661                 :      227985 :                       && ((TREE_CODE (base_ref) == MEM_REF
    1662                 :      224738 :                            && ((offset2 == instance_offset
    1663                 :      222647 :                                 && TREE_OPERAND (base_ref, 0) == instance)
    1664                 :       15459 :                                || (!offset2
    1665                 :       15459 :                                    && TREE_OPERAND (base_ref, 0)
    1666                 :             :                                       == otr_object)))
    1667                 :       17016 :                           || (DECL_P (instance) && base_ref == instance
    1668                 :        3086 :                               && offset2 == instance_offset)))
    1669                 :             :                     {
    1670                 :      214055 :                       stmt = SSA_NAME_DEF_STMT (ref);
    1671                 :      214055 :                       instance_ref = ref_exp;
    1672                 :             :                     }
    1673                 :             :                 }
    1674                 :             :             }
    1675                 :             :         }
    1676                 :             :     }
    1677                 :             :  
    1678                 :             :   /* If we failed to look up the reference in code, build our own.  */
    1679                 :     2917249 :   if (!instance_ref)
    1680                 :             :     {
    1681                 :             :       /* If the statement in question does not use memory, we can't tell
    1682                 :             :          anything.  */
    1683                 :     8147324 :       if (!gimple_vuse (stmt))
    1684                 :             :         return false;
    1685                 :     2694814 :       ao_ref_init_from_ptr_and_size (&ao, otr_object, NULL);
    1686                 :             :     }
    1687                 :             :   else
    1688                 :             :   /* Otherwise use the real reference.  */
    1689                 :      214055 :     ao_ref_init (&ao, instance_ref);
    1690                 :             : 
    1691                 :             :   /* We look for vtbl pointer read.  */
    1692                 :     3141513 :   ao.size = POINTER_SIZE;
    1693                 :     2908869 :   ao.max_size = ao.size;
    1694                 :             :   /* We are looking for stores to vptr pointer within the instance of
    1695                 :             :      outer type.
    1696                 :             :      TODO: The vptr pointer type is globally known, we probably should
    1697                 :             :      keep it and do that even when otr_type is unknown.  */
    1698                 :     2908869 :   if (otr_type)
    1699                 :             :     {
    1700                 :      192835 :       ao.base_alias_set
    1701                 :      364069 :         = get_alias_set (outer_type ? outer_type : otr_type);
    1702                 :      192835 :       ao.ref_alias_set
    1703                 :      192835 :         = get_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type))));
    1704                 :             :     }
    1705                 :             : 
    1706                 :     2908869 :   if (dump_file)
    1707                 :             :     {
    1708                 :         722 :       fprintf (dump_file, "Determining dynamic type for call: ");
    1709                 :         722 :       print_gimple_stmt (dump_file, call, 0);
    1710                 :         722 :       fprintf (dump_file, "  Starting walk at: ");
    1711                 :         722 :       print_gimple_stmt (dump_file, stmt, 0);
    1712                 :         722 :       fprintf (dump_file, "  instance pointer: ");
    1713                 :         722 :       print_generic_expr (dump_file, otr_object, TDF_SLIM);
    1714                 :         722 :       fprintf (dump_file, "  Outer instance pointer: ");
    1715                 :         722 :       print_generic_expr (dump_file, instance, TDF_SLIM);
    1716                 :         722 :       fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
    1717                 :         722 :       fprintf (dump_file, " vtbl reference: ");
    1718                 :         722 :       print_generic_expr (dump_file, instance_ref, TDF_SLIM);
    1719                 :         722 :       fprintf (dump_file, "\n");
    1720                 :             :     }
    1721                 :             : 
    1722                 :     2908869 :   tci.offset = instance_offset;
    1723                 :     2908869 :   tci.instance = instance;
    1724                 :     2908869 :   tci.vtbl_ptr_ref = instance_ref;
    1725                 :     2908869 :   tci.known_current_type = NULL_TREE;
    1726                 :     2908869 :   tci.known_current_offset = 0;
    1727                 :     2908869 :   tci.otr_type = otr_type;
    1728                 :     2908869 :   tci.type_maybe_changed = false;
    1729                 :     2908869 :   tci.multiple_types_encountered = false;
    1730                 :     2908869 :   tci.speculative = 0;
    1731                 :     2908869 :   tci.seen_unanalyzed_store = false;
    1732                 :             : 
    1733                 :     2908869 :   unsigned aa_walk_budget = 0;
    1734                 :     2908869 :   if (aa_walk_budget_p)
    1735                 :     2740090 :     aa_walk_budget = *aa_walk_budget_p + 1;
    1736                 :             : 
    1737                 :     2908869 :   int walked
    1738                 :     2908869 :    = walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
    1739                 :             :                          &tci, NULL, &function_entry_reached, aa_walk_budget);
    1740                 :             : 
    1741                 :             :   /* If we did not find any type changing statements, we may still drop
    1742                 :             :      maybe_in_construction flag if the context already have outer type. 
    1743                 :             : 
    1744                 :             :      Here we make special assumptions about both constructors and
    1745                 :             :      destructors which are all the functions that are allowed to alter the
    1746                 :             :      VMT pointers.  It assumes that destructors begin with assignment into
    1747                 :             :      all VMT pointers and that constructors essentially look in the
    1748                 :             :      following way:
    1749                 :             : 
    1750                 :             :      1) The very first thing they do is that they call constructors of
    1751                 :             :      ancestor sub-objects that have them.
    1752                 :             : 
    1753                 :             :      2) Then VMT pointers of this and all its ancestors is set to new
    1754                 :             :      values corresponding to the type corresponding to the constructor.
    1755                 :             : 
    1756                 :             :      3) Only afterwards, other stuff such as constructor of member
    1757                 :             :      sub-objects and the code written by the user is run.  Only this may
    1758                 :             :      include calling virtual functions, directly or indirectly.
    1759                 :             : 
    1760                 :             :      4) placement new cannot be used to change type of non-POD statically
    1761                 :             :      allocated variables.
    1762                 :             : 
    1763                 :             :      There is no way to call a constructor of an ancestor sub-object in any
    1764                 :             :      other way.
    1765                 :             : 
    1766                 :             :      This means that we do not have to care whether constructors get the
    1767                 :             :      correct type information because they will always change it (in fact,
    1768                 :             :      if we define the type to be given by the VMT pointer, it is undefined).
    1769                 :             : 
    1770                 :             :      The most important fact to derive from the above is that if, for some
    1771                 :             :      statement in the section 3, we try to detect whether the dynamic type
    1772                 :             :      has changed, we can safely ignore all calls as we examine the function
    1773                 :             :      body backwards until we reach statements in section 2 because these
    1774                 :             :      calls cannot be ancestor constructors or destructors (if the input is
    1775                 :             :      not bogus) and so do not change the dynamic type (this holds true only
    1776                 :             :      for automatically allocated objects but at the moment we devirtualize
    1777                 :             :      only these).  We then must detect that statements in section 2 change
    1778                 :             :      the dynamic type and can try to derive the new type.  That is enough
    1779                 :             :      and we can stop, we will never see the calls into constructors of
    1780                 :             :      sub-objects in this code. 
    1781                 :             : 
    1782                 :             :      Therefore if the static outer type was found (outer_type)
    1783                 :             :      we can safely ignore tci.speculative that is set on calls and give up
    1784                 :             :      only if there was dynamic type store that may affect given variable
    1785                 :             :      (seen_unanalyzed_store)  */
    1786                 :             : 
    1787                 :     2908869 :   if (walked < 0)
    1788                 :             :     {
    1789                 :       88086 :       if (dump_file)
    1790                 :           0 :         fprintf (dump_file, "  AA walk budget exhausted.\n");
    1791                 :       88086 :       *aa_walk_budget_p = 0;
    1792                 :       88086 :       return false;
    1793                 :             :     }
    1794                 :     2820783 :   else if (aa_walk_budget_p)
    1795                 :     2652004 :     *aa_walk_budget_p -= walked;
    1796                 :             : 
    1797                 :     2820783 :   if (!tci.type_maybe_changed
    1798                 :     2820783 :       || (outer_type
    1799                 :       20131 :           && !dynamic
    1800                 :        2567 :           && !tci.seen_unanalyzed_store
    1801                 :        2567 :           && !tci.multiple_types_encountered
    1802                 :        2567 :           && ((offset == tci.offset
    1803                 :        2386 :                && types_same_for_odr (tci.known_current_type,
    1804                 :             :                                       outer_type))
    1805                 :         428 :                || (instance_offset == offset
    1806                 :         247 :                    && types_same_for_odr (tci.known_current_type,
    1807                 :             :                                           instance_outer_type)))))
    1808                 :             :     {
    1809                 :     2712084 :       if (!outer_type || tci.seen_unanalyzed_store)
    1810                 :             :         return false;
    1811                 :      195704 :       if (maybe_in_construction)
    1812                 :      135097 :         maybe_in_construction = false;
    1813                 :      195704 :       if (dump_file)
    1814                 :         283 :         fprintf (dump_file, "  No dynamic type change found.\n");
    1815                 :      195704 :       return true;
    1816                 :             :     }
    1817                 :             : 
    1818                 :      108699 :   if (tci.known_current_type
    1819                 :      108699 :       && !function_entry_reached
    1820                 :      105283 :       && !tci.multiple_types_encountered)
    1821                 :             :     {
    1822                 :      105281 :       if (!tci.speculative)
    1823                 :             :         {
    1824                 :       34926 :           outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
    1825                 :       34926 :           offset = tci.known_current_offset;
    1826                 :       34926 :           dynamic = true;
    1827                 :       34926 :           maybe_in_construction = false;
    1828                 :       34926 :           maybe_derived_type = false;
    1829                 :       34926 :           if (dump_file)
    1830                 :          37 :             fprintf (dump_file, "  Determined dynamic type.\n");
    1831                 :             :         }
    1832                 :       70355 :       else if (!speculative_outer_type
    1833                 :        5016 :                || speculative_maybe_derived_type)
    1834                 :             :         {
    1835                 :       70355 :           speculative_outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
    1836                 :       70355 :           speculative_offset = tci.known_current_offset;
    1837                 :       70355 :           speculative_maybe_derived_type = false;
    1838                 :       70355 :           if (dump_file)
    1839                 :          10 :             fprintf (dump_file, "  Determined speculative dynamic type.\n");
    1840                 :             :         }
    1841                 :             :     }
    1842                 :        3418 :   else if (dump_file)
    1843                 :             :     {
    1844                 :           0 :       fprintf (dump_file, "  Found multiple types%s%s\n",
    1845                 :             :                function_entry_reached ? " (function entry reached)" : "",
    1846                 :             :                function_entry_reached ? " (multiple types encountered)" : "");
    1847                 :             :     }
    1848                 :             : 
    1849                 :             :   return false;
    1850                 :             : }
    1851                 :             : 
    1852                 :             : /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
    1853                 :             :    seems consistent (and useful) with what we already have in the non-speculative context.  */
    1854                 :             : 
    1855                 :             : bool
    1856                 :     3947200 : ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type,
    1857                 :             :                                                         HOST_WIDE_INT spec_offset,
    1858                 :             :                                                         bool spec_maybe_derived_type,
    1859                 :             :                                                         tree otr_type) const
    1860                 :             : {
    1861                 :     3947200 :   if (!flag_devirtualize_speculatively)
    1862                 :             :     return false;
    1863                 :             : 
    1864                 :             :   /* Non-polymorphic types are useless for deriving likely polymorphic
    1865                 :             :      call targets.  */
    1866                 :     3937180 :   if (!spec_outer_type || !contains_polymorphic_type_p (spec_outer_type))
    1867                 :     2978162 :     return false;
    1868                 :             : 
    1869                 :             :   /* If we know nothing, speculation is always good.  */
    1870                 :      959018 :   if (!outer_type)
    1871                 :             :     return true;
    1872                 :             : 
    1873                 :             :   /* Speculation is only useful to avoid derived types.
    1874                 :             :      This is not 100% true for placement new, where the outer context may
    1875                 :             :      turn out to be useless, but ignore these for now.  */
    1876                 :      717517 :   if (!maybe_derived_type)
    1877                 :             :     return false;
    1878                 :             : 
    1879                 :             :   /* If types agrees, speculation is consistent, but it makes sense only
    1880                 :             :      when it says something new.  */
    1881                 :      698838 :   if (types_must_be_same_for_odr (spec_outer_type, outer_type))
    1882                 :      978761 :     return maybe_derived_type && !spec_maybe_derived_type;
    1883                 :             : 
    1884                 :             :   /* If speculation does not contain the type in question, ignore it.  */
    1885                 :      209372 :   if (otr_type
    1886                 :      209372 :       && !contains_type_p (spec_outer_type, spec_offset, otr_type, false, true))
    1887                 :             :     return false;
    1888                 :             : 
    1889                 :             :   /* If outer type already contains speculation as a filed,
    1890                 :             :      it is useless.  We already know from OUTER_TYPE 
    1891                 :             :      SPEC_TYPE and that it is not in the construction.  */
    1892                 :      208448 :   if (contains_type_p (outer_type, offset - spec_offset,
    1893                 :             :                        spec_outer_type, false, false))
    1894                 :             :     return false;
    1895                 :             : 
    1896                 :             :   /* If speculative outer type is not more specified than outer
    1897                 :             :      type, just give up. 
    1898                 :             :      We can only decide this safely if we can compare types with OUTER_TYPE.
    1899                 :             :    */
    1900                 :          57 :   if ((!in_lto_p || odr_type_p (outer_type))
    1901                 :      416670 :       && !contains_type_p (spec_outer_type,
    1902                 :      208335 :                            spec_offset - offset,
    1903                 :      208335 :                            outer_type, false))
    1904                 :             :     return false;
    1905                 :             :   return true;
    1906                 :             : }
    1907                 :             : 
    1908                 :             : /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
    1909                 :             :    NEW_MAYBE_DERIVED_TYPE 
    1910                 :             :    If OTR_TYPE is set, assume the context is used with OTR_TYPE.  */
    1911                 :             : 
    1912                 :             : bool
    1913                 :     3906629 : ipa_polymorphic_call_context::combine_speculation_with
    1914                 :             :    (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
    1915                 :             :     tree otr_type)
    1916                 :             : {
    1917                 :     3906629 :   if (!new_outer_type)
    1918                 :             :     return false;
    1919                 :             : 
    1920                 :             :   /* restrict_to_inner_class may eliminate wrong speculation making our job
    1921                 :             :      easier.  */
    1922                 :     3844952 :   if (otr_type)
    1923                 :        2721 :     restrict_to_inner_class (otr_type);
    1924                 :             : 
    1925                 :     3844952 :   if (!speculation_consistent_p (new_outer_type, new_offset,
    1926                 :             :                                  new_maybe_derived_type, otr_type))
    1927                 :             :     return false;
    1928                 :             : 
    1929                 :             :   /* New speculation is a win in case we have no speculation or new
    1930                 :             :      speculation does not consider derivations.  */
    1931                 :      302903 :   if (!speculative_outer_type
    1932                 :       86276 :       || (speculative_maybe_derived_type
    1933                 :       85526 :           && !new_maybe_derived_type))
    1934                 :             :     {
    1935                 :      220972 :       speculative_outer_type = new_outer_type;
    1936                 :      220972 :       speculative_offset = new_offset;
    1937                 :      220972 :       speculative_maybe_derived_type = new_maybe_derived_type;
    1938                 :      220972 :       return true;
    1939                 :             :     }
    1940                 :       81931 :   else if (types_must_be_same_for_odr (speculative_outer_type,
    1941                 :             :                                        new_outer_type))
    1942                 :             :     {
    1943                 :       60235 :       if (speculative_offset != new_offset)
    1944                 :             :         {
    1945                 :             :           /* OK we have two contexts that seems valid but they disagree,
    1946                 :             :              just give up.
    1947                 :             : 
    1948                 :             :              This is not a lattice operation, so we may want to drop it later.  */
    1949                 :           4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1950                 :           0 :             fprintf (dump_file,
    1951                 :             :                      "Speculative outer types match, "
    1952                 :             :                      "offset mismatch -> invalid speculation\n");
    1953                 :           4 :           clear_speculation ();
    1954                 :           4 :           return true;
    1955                 :             :         }
    1956                 :             :       else
    1957                 :             :         {
    1958                 :       60231 :           if (speculative_maybe_derived_type && !new_maybe_derived_type)
    1959                 :             :             {
    1960                 :           0 :               speculative_maybe_derived_type = false;
    1961                 :           0 :               return true;
    1962                 :             :             }
    1963                 :             :           else
    1964                 :             :             return false;
    1965                 :             :         }
    1966                 :             :     }
    1967                 :             :   /* Choose type that contains the other.  This one either contains the outer
    1968                 :             :      as a field (thus giving exactly one target) or is deeper in the type
    1969                 :             :      hierarchy.  */
    1970                 :       21696 :   else if (speculative_outer_type
    1971                 :       21696 :            && speculative_maybe_derived_type
    1972                 :       42910 :            && (new_offset > speculative_offset
    1973                 :       20627 :                || (new_offset == speculative_offset
    1974                 :       20585 :                    && contains_type_p (new_outer_type,
    1975                 :             :                                        0, speculative_outer_type, false))))
    1976                 :             :     {
    1977                 :        1011 :       tree old_outer_type = speculative_outer_type;
    1978                 :        1011 :       HOST_WIDE_INT old_offset = speculative_offset;
    1979                 :        1011 :       bool old_maybe_derived_type = speculative_maybe_derived_type;
    1980                 :             : 
    1981                 :        1011 :       speculative_outer_type = new_outer_type;
    1982                 :        1011 :       speculative_offset = new_offset;
    1983                 :        1011 :       speculative_maybe_derived_type = new_maybe_derived_type;
    1984                 :             : 
    1985                 :        1011 :       if (otr_type)
    1986                 :           0 :         restrict_to_inner_class (otr_type);
    1987                 :             : 
    1988                 :             :       /* If the speculation turned out to make no sense, revert to sensible
    1989                 :             :          one.  */
    1990                 :        1011 :       if (!speculative_outer_type)
    1991                 :             :         {
    1992                 :           0 :           speculative_outer_type = old_outer_type;
    1993                 :           0 :           speculative_offset = old_offset;
    1994                 :           0 :           speculative_maybe_derived_type = old_maybe_derived_type;
    1995                 :           0 :           return false;
    1996                 :             :         }
    1997                 :        1011 :       return (old_offset != speculative_offset
    1998                 :         424 :               || old_maybe_derived_type != speculative_maybe_derived_type
    1999                 :        1435 :               || types_must_be_same_for_odr (speculative_outer_type,
    2000                 :             :                                              new_outer_type));
    2001                 :             :     }
    2002                 :             :   return false;
    2003                 :             : }
    2004                 :             : 
    2005                 :             : /* Make speculation less specific so
    2006                 :             :    NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
    2007                 :             :    If OTR_TYPE is set, assume the context is used with OTR_TYPE.  */
    2008                 :             : 
    2009                 :             : bool
    2010                 :          57 : ipa_polymorphic_call_context::meet_speculation_with
    2011                 :             :    (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
    2012                 :             :     tree otr_type)
    2013                 :             : {
    2014                 :          57 :   if (!new_outer_type && speculative_outer_type)
    2015                 :             :     {
    2016                 :          20 :       clear_speculation ();
    2017                 :          20 :       return true;
    2018                 :             :     }
    2019                 :             : 
    2020                 :             :   /* restrict_to_inner_class may eliminate wrong speculation making our job
    2021                 :             :      easier.  */
    2022                 :          37 :   if (otr_type)
    2023                 :           0 :     restrict_to_inner_class (otr_type);
    2024                 :             : 
    2025                 :          37 :   if (!speculative_outer_type
    2026                 :          55 :       || !speculation_consistent_p (speculative_outer_type,
    2027                 :             :                                     speculative_offset,
    2028                 :          18 :                                     speculative_maybe_derived_type,
    2029                 :             :                                     otr_type))
    2030                 :          20 :     return false;
    2031                 :             : 
    2032                 :          17 :   if (!speculation_consistent_p (new_outer_type, new_offset,
    2033                 :             :                                  new_maybe_derived_type, otr_type))
    2034                 :             :     {
    2035                 :           0 :       clear_speculation ();
    2036                 :           0 :       return true;
    2037                 :             :     }
    2038                 :             : 
    2039                 :          17 :   else if (types_must_be_same_for_odr (speculative_outer_type,
    2040                 :             :                                        new_outer_type))
    2041                 :             :     {
    2042                 :          17 :       if (speculative_offset != new_offset)
    2043                 :             :         {
    2044                 :           0 :           clear_speculation ();
    2045                 :           0 :           return true;
    2046                 :             :         }
    2047                 :             :       else
    2048                 :             :         {
    2049                 :          17 :           if (!speculative_maybe_derived_type && new_maybe_derived_type)
    2050                 :             :             {
    2051                 :           0 :               speculative_maybe_derived_type = true;
    2052                 :           0 :               return true;
    2053                 :             :             }
    2054                 :             :           else
    2055                 :             :             return false;
    2056                 :             :         }
    2057                 :             :     }
    2058                 :             :   /* See if one type contains the other as a field (not base).  */
    2059                 :           0 :   else if (contains_type_p (new_outer_type, new_offset - speculative_offset,
    2060                 :             :                             speculative_outer_type, false, false))
    2061                 :             :     return false;
    2062                 :           0 :   else if (contains_type_p (speculative_outer_type,
    2063                 :           0 :                             speculative_offset - new_offset,
    2064                 :             :                             new_outer_type, false, false))
    2065                 :             :     {
    2066                 :           0 :       speculative_outer_type = new_outer_type;
    2067                 :           0 :       speculative_offset = new_offset;
    2068                 :           0 :       speculative_maybe_derived_type = new_maybe_derived_type;
    2069                 :           0 :       return true;
    2070                 :             :     }
    2071                 :             :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2072                 :           0 :   else if (contains_type_p (new_outer_type,
    2073                 :           0 :                             new_offset - speculative_offset,
    2074                 :             :                             speculative_outer_type, false, true))
    2075                 :             :     {
    2076                 :           0 :       if (!speculative_maybe_derived_type)
    2077                 :             :         {
    2078                 :           0 :           speculative_maybe_derived_type = true;
    2079                 :           0 :           return true;
    2080                 :             :         }
    2081                 :             :       return false;
    2082                 :             :     }
    2083                 :             :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2084                 :           0 :   else if (contains_type_p (speculative_outer_type,
    2085                 :           0 :                             speculative_offset - new_offset, new_outer_type, false, true))
    2086                 :             :     {
    2087                 :           0 :       speculative_outer_type = new_outer_type;
    2088                 :           0 :       speculative_offset = new_offset;
    2089                 :           0 :       speculative_maybe_derived_type = true;
    2090                 :           0 :       return true;
    2091                 :             :     }
    2092                 :             :   else
    2093                 :             :     {
    2094                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2095                 :           0 :         fprintf (dump_file, "Giving up on speculative meet\n");
    2096                 :           0 :       clear_speculation ();
    2097                 :           0 :       return true;
    2098                 :             :     }
    2099                 :             : }
    2100                 :             : 
    2101                 :             : /* Assume that both THIS and a given context is valid and strengthen THIS
    2102                 :             :    if possible.  Return true if any strengthening was made.
    2103                 :             :    If actual type the context is being used in is known, OTR_TYPE should be
    2104                 :             :    set accordingly. This improves quality of combined result.  */
    2105                 :             : 
    2106                 :             : bool
    2107                 :      122289 : ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
    2108                 :             :                                             tree otr_type)
    2109                 :             : {
    2110                 :      122289 :   bool updated = false;
    2111                 :             : 
    2112                 :      176103 :   if (ctx.useless_p () || invalid)
    2113                 :             :     return false;
    2114                 :             : 
    2115                 :             :   /* Restricting context to inner type makes merging easier, however do not
    2116                 :             :      do that unless we know how the context is used (OTR_TYPE is non-NULL)  */
    2117                 :      121703 :   if (otr_type && !invalid && !ctx.invalid)
    2118                 :             :     {
    2119                 :       26124 :       restrict_to_inner_class (otr_type);
    2120                 :       26124 :       ctx.restrict_to_inner_class (otr_type);
    2121                 :       26124 :       if(invalid)
    2122                 :             :         return false;
    2123                 :             :     }
    2124                 :             : 
    2125                 :      121635 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2126                 :             :     {
    2127                 :         122 :       fprintf (dump_file, "Polymorphic call context combine:");
    2128                 :         122 :       dump (dump_file);
    2129                 :         122 :       fprintf (dump_file, "With context:                    ");
    2130                 :         122 :       ctx.dump (dump_file);
    2131                 :         122 :       if (otr_type)
    2132                 :             :         {
    2133                 :          46 :           fprintf (dump_file, "To be used with type:            ");
    2134                 :          46 :           print_generic_expr (dump_file, otr_type, TDF_SLIM);
    2135                 :          46 :           fprintf (dump_file, "\n");
    2136                 :             :         }
    2137                 :             :     }
    2138                 :             : 
    2139                 :             :   /* If call is known to be invalid, we are done.  */
    2140                 :      121635 :   if (ctx.invalid)
    2141                 :             :     {
    2142                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2143                 :           0 :         fprintf (dump_file, "-> Invalid context\n");
    2144                 :           0 :       goto invalidate;
    2145                 :             :     }
    2146                 :             : 
    2147                 :      121635 :   if (!ctx.outer_type)
    2148                 :             :     ;
    2149                 :       68608 :   else if (!outer_type)
    2150                 :             :     {
    2151                 :       16186 :       outer_type = ctx.outer_type;
    2152                 :       16186 :       offset = ctx.offset;
    2153                 :       16186 :       dynamic = ctx.dynamic;
    2154                 :       16186 :       maybe_in_construction = ctx.maybe_in_construction;
    2155                 :       16186 :       maybe_derived_type = ctx.maybe_derived_type;
    2156                 :       16186 :       updated = true;
    2157                 :             :     }
    2158                 :             :   /* If types are known to be same, merging is quite easy.  */
    2159                 :       52422 :   else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
    2160                 :             :     {
    2161                 :       34779 :       if (offset != ctx.offset
    2162                 :           4 :           && TYPE_SIZE (outer_type)
    2163                 :       34783 :           && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
    2164                 :             :         {
    2165                 :           4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2166                 :           0 :             fprintf (dump_file, "Outer types match, offset mismatch -> invalid\n");
    2167                 :           4 :           clear_speculation ();
    2168                 :           4 :           clear_outer_type ();
    2169                 :           4 :           invalid = true;
    2170                 :           4 :           return true;
    2171                 :             :         }
    2172                 :       34775 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2173                 :          40 :         fprintf (dump_file, "Outer types match, merging flags\n");
    2174                 :       34775 :       if (maybe_in_construction && !ctx.maybe_in_construction)
    2175                 :             :         {
    2176                 :       10817 :           updated = true;
    2177                 :       10817 :           maybe_in_construction = false;
    2178                 :             :         }
    2179                 :       34775 :       if (maybe_derived_type && !ctx.maybe_derived_type)
    2180                 :             :         {
    2181                 :        1887 :           updated = true;
    2182                 :        1887 :           maybe_derived_type = false;
    2183                 :             :         }
    2184                 :       34775 :       if (dynamic && !ctx.dynamic)
    2185                 :             :         {
    2186                 :       10718 :           updated = true;
    2187                 :       10718 :           dynamic = false;
    2188                 :             :         }
    2189                 :             :     }
    2190                 :             :   /* If we know the type precisely, there is not much to improve.  */
    2191                 :       17643 :   else if (!maybe_derived_type && !maybe_in_construction
    2192                 :       13033 :            && !ctx.maybe_derived_type && !ctx.maybe_in_construction)
    2193                 :             :     {
    2194                 :             :       /* It may be easy to check if second context permits the first
    2195                 :             :          and set INVALID otherwise.  This is not easy to do in general;
    2196                 :             :          contains_type_p may return false negatives for non-comparable
    2197                 :             :          types.  
    2198                 :             : 
    2199                 :             :          If OTR_TYPE is known, we however can expect that
    2200                 :             :          restrict_to_inner_class should have discovered the same base
    2201                 :             :          type.  */
    2202                 :         411 :       if (otr_type && !ctx.maybe_in_construction && !ctx.maybe_derived_type)
    2203                 :             :         {
    2204                 :           0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2205                 :           0 :             fprintf (dump_file, "Contextes disagree -> invalid\n");
    2206                 :           0 :           goto invalidate;
    2207                 :             :         }
    2208                 :             :     }
    2209                 :             :   /* See if one type contains the other as a field (not base).
    2210                 :             :      In this case we want to choose the wider type, because it contains
    2211                 :             :      more information.  */
    2212                 :       17232 :   else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
    2213                 :             :                             outer_type, false, false))
    2214                 :             :     {
    2215                 :        1898 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2216                 :           0 :         fprintf (dump_file, "Second type contain the first as a field\n");
    2217                 :             : 
    2218                 :        1898 :       if (maybe_derived_type)
    2219                 :             :         {
    2220                 :        1219 :           outer_type = ctx.outer_type;
    2221                 :        1219 :           maybe_derived_type = ctx.maybe_derived_type;
    2222                 :        1219 :           offset = ctx.offset;
    2223                 :        1219 :           dynamic = ctx.dynamic;
    2224                 :        1219 :           updated = true;
    2225                 :             :         }
    2226                 :             : 
    2227                 :             :       /* If we do not know how the context is being used, we cannot
    2228                 :             :          clear MAYBE_IN_CONSTRUCTION because it may be offseted
    2229                 :             :          to other component of OUTER_TYPE later and we know nothing
    2230                 :             :          about it.  */
    2231                 :        1898 :       if (otr_type && maybe_in_construction
    2232                 :           0 :           && !ctx.maybe_in_construction)
    2233                 :             :         {
    2234                 :           0 :           maybe_in_construction = false;
    2235                 :           0 :           updated = true;
    2236                 :             :         }
    2237                 :             :     }
    2238                 :       15334 :   else if (contains_type_p (outer_type, offset - ctx.offset,
    2239                 :             :                             ctx.outer_type, false, false))
    2240                 :             :     {
    2241                 :          50 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2242                 :           0 :         fprintf (dump_file, "First type contain the second as a field\n");
    2243                 :             : 
    2244                 :          50 :       if (otr_type && maybe_in_construction
    2245                 :           0 :           && !ctx.maybe_in_construction)
    2246                 :             :         {
    2247                 :           0 :           maybe_in_construction = false;
    2248                 :           0 :           updated = true;
    2249                 :             :         }
    2250                 :             :     }
    2251                 :             :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2252                 :       15284 :   else if (contains_type_p (ctx.outer_type,
    2253                 :       15284 :                             ctx.offset - offset, outer_type, false, true))
    2254                 :             :     {
    2255                 :        7378 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2256                 :          16 :         fprintf (dump_file, "First type is base of second\n");
    2257                 :        7378 :       if (!maybe_derived_type)
    2258                 :             :         {
    2259                 :        4551 :           if (!ctx.maybe_in_construction
    2260                 :        4551 :               && types_odr_comparable (outer_type, ctx.outer_type))
    2261                 :             :             {
    2262                 :           0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2263                 :           0 :                 fprintf (dump_file, "Second context does not permit base -> invalid\n");
    2264                 :           0 :               goto invalidate;
    2265                 :             :             }
    2266                 :             :         }
    2267                 :             :       /* Pick variant deeper in the hierarchy.  */
    2268                 :             :       else
    2269                 :             :         {
    2270                 :        2827 :           outer_type = ctx.outer_type;
    2271                 :        2827 :           maybe_in_construction = ctx.maybe_in_construction;
    2272                 :        2827 :           maybe_derived_type = ctx.maybe_derived_type;
    2273                 :        2827 :           offset = ctx.offset;
    2274                 :        2827 :           dynamic = ctx.dynamic;
    2275                 :        2827 :           updated = true;
    2276                 :             :         }
    2277                 :             :     }
    2278                 :             :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2279                 :        7906 :   else if (contains_type_p (outer_type,
    2280                 :        7906 :                             offset - ctx.offset, ctx.outer_type, false, true))
    2281                 :             :     {
    2282                 :        7765 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2283                 :          34 :         fprintf (dump_file, "Second type is base of first\n");
    2284                 :        7765 :       if (!ctx.maybe_derived_type)
    2285                 :             :         {
    2286                 :         125 :           if (!maybe_in_construction
    2287                 :         125 :               && types_odr_comparable (outer_type, ctx.outer_type))
    2288                 :             :             {
    2289                 :           0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2290                 :           0 :                 fprintf (dump_file, "First context does not permit base -> invalid\n");
    2291                 :           0 :               goto invalidate;
    2292                 :             :             }
    2293                 :             :           /* Pick the base type.  */
    2294                 :         125 :           else if (maybe_in_construction)
    2295                 :             :             {
    2296                 :         125 :               outer_type = ctx.outer_type;
    2297                 :         125 :               maybe_in_construction = ctx.maybe_in_construction;
    2298                 :         125 :               maybe_derived_type = ctx.maybe_derived_type;
    2299                 :         125 :               offset = ctx.offset;
    2300                 :         125 :               dynamic = ctx.dynamic;
    2301                 :         125 :               updated = true;
    2302                 :             :             }
    2303                 :             :         }
    2304                 :             :     }
    2305                 :             :   /* TODO handle merging using hierarchy. */
    2306                 :         141 :   else if (dump_file && (dump_flags & TDF_DETAILS))
    2307                 :           4 :     fprintf (dump_file, "Giving up on merge\n");
    2308                 :             : 
    2309                 :      243262 :   updated |= combine_speculation_with (ctx.speculative_outer_type,
    2310                 :             :                                        ctx.speculative_offset,
    2311                 :      121631 :                                        ctx.speculative_maybe_derived_type,
    2312                 :             :                                        otr_type);
    2313                 :             : 
    2314                 :      121631 :   if (updated && dump_file && (dump_flags & TDF_DETAILS))
    2315                 :             :     {
    2316                 :          64 :       fprintf (dump_file, "Updated as:                      ");
    2317                 :          64 :       dump (dump_file);
    2318                 :          64 :       fprintf (dump_file, "\n");
    2319                 :             :     }
    2320                 :             :   return updated;
    2321                 :             : 
    2322                 :           0 : invalidate:
    2323                 :           0 :   invalid = true;
    2324                 :           0 :   clear_speculation ();
    2325                 :           0 :   clear_outer_type ();
    2326                 :           0 :   return true;
    2327                 :             : }
    2328                 :             : 
    2329                 :             : /* Take non-speculative info, merge it with speculative and clear speculation.
    2330                 :             :    Used when we no longer manage to keep track of actual outer type, but we
    2331                 :             :    think it is still there.
    2332                 :             : 
    2333                 :             :    If OTR_TYPE is set, the transformation can be done more effectively assuming
    2334                 :             :    that context is going to be used only that way.  */
    2335                 :             : 
    2336                 :             : void
    2337                 :       82264 : ipa_polymorphic_call_context::make_speculative (tree otr_type)
    2338                 :             : {
    2339                 :       82264 :   tree spec_outer_type = outer_type;
    2340                 :       82264 :   HOST_WIDE_INT spec_offset = offset;
    2341                 :       82264 :   bool spec_maybe_derived_type = maybe_derived_type;
    2342                 :             : 
    2343                 :       82264 :   if (invalid)
    2344                 :             :     {
    2345                 :           0 :       invalid = false;
    2346                 :           0 :       clear_outer_type ();
    2347                 :           0 :       clear_speculation ();
    2348                 :           0 :       return;
    2349                 :             :     }
    2350                 :       82264 :   if (!outer_type)
    2351                 :             :     return;
    2352                 :       21641 :   clear_outer_type ();
    2353                 :       21641 :   combine_speculation_with (spec_outer_type, spec_offset,
    2354                 :             :                             spec_maybe_derived_type,
    2355                 :             :                             otr_type);
    2356                 :             : }
    2357                 :             : 
    2358                 :             : /* Use when we cannot track dynamic type change.  This speculatively assume
    2359                 :             :    type change is not happening.  */
    2360                 :             : 
    2361                 :             : void
    2362                 :      105100 : ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
    2363                 :             :                                                             tree otr_type)
    2364                 :             : {
    2365                 :      105100 :   if (dynamic)
    2366                 :       82264 :     make_speculative (otr_type);
    2367                 :       22836 :   else if (in_poly_cdtor)
    2368                 :       14999 :     maybe_in_construction = true;
    2369                 :      105100 : }
    2370                 :             : 
    2371                 :             : /* Return TRUE if this context conveys the same information as OTHER.  */
    2372                 :             : 
    2373                 :             : bool
    2374                 :       49305 : ipa_polymorphic_call_context::equal_to
    2375                 :             :     (const ipa_polymorphic_call_context &x) const
    2376                 :             : {
    2377                 :       49305 :   if (useless_p ())
    2378                 :         123 :     return x.useless_p ();
    2379                 :       49182 :   if (invalid)
    2380                 :           0 :     return x.invalid;
    2381                 :       86303 :   if (x.useless_p () || x.invalid)
    2382                 :             :     return false;
    2383                 :             : 
    2384                 :       49178 :   if (outer_type)
    2385                 :             :     {
    2386                 :       13340 :       if (!x.outer_type
    2387                 :       13224 :           || !types_odr_comparable (outer_type, x.outer_type)
    2388                 :       13224 :           || !types_same_for_odr (outer_type, x.outer_type)
    2389                 :       12877 :           || offset != x.offset
    2390                 :       12854 :           || maybe_in_construction != x.maybe_in_construction
    2391                 :             :           || maybe_derived_type != x.maybe_derived_type
    2392                 :       26194 :           || dynamic != x.dynamic)
    2393                 :         664 :         return false;
    2394                 :             :     }
    2395                 :       35838 :   else if (x.outer_type)
    2396                 :             :     return false;
    2397                 :             : 
    2398                 :             : 
    2399                 :       48143 :   if (speculative_outer_type
    2400                 :       84807 :       && speculation_consistent_p (speculative_outer_type, speculative_offset,
    2401                 :       36664 :                                    speculative_maybe_derived_type, NULL_TREE))
    2402                 :             :     {
    2403                 :       35236 :       if (!x.speculative_outer_type)
    2404                 :             :         return false;
    2405                 :             : 
    2406                 :       35236 :       if (!types_odr_comparable (speculative_outer_type,
    2407                 :             :                                  x.speculative_outer_type)
    2408                 :       35236 :           || !types_same_for_odr  (speculative_outer_type,
    2409                 :       35236 :                                    x.speculative_outer_type)
    2410                 :       34940 :           || speculative_offset != x.speculative_offset
    2411                 :       70112 :           || speculative_maybe_derived_type != x.speculative_maybe_derived_type)
    2412                 :         363 :         return false;
    2413                 :             :     }
    2414                 :       12907 :   else if (x.speculative_outer_type
    2415                 :       14234 :            && x.speculation_consistent_p (x.speculative_outer_type,
    2416                 :        1327 :                                           x.speculative_offset,
    2417                 :        1327 :                                           x.speculative_maybe_derived_type,
    2418                 :             :                                           NULL))
    2419                 :             :     return false;
    2420                 :             : 
    2421                 :             :   return true;
    2422                 :             : }
    2423                 :             : 
    2424                 :             : /* Modify context to be strictly less restrictive than CTX.  */
    2425                 :             : 
    2426                 :             : bool
    2427                 :          98 : ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx,
    2428                 :             :                                          tree otr_type)
    2429                 :             : {
    2430                 :          98 :   bool updated = false;
    2431                 :             : 
    2432                 :         180 :   if (useless_p () || ctx.invalid)
    2433                 :             :     return false;
    2434                 :             : 
    2435                 :             :   /* Restricting context to inner type makes merging easier, however do not
    2436                 :             :      do that unless we know how the context is used (OTR_TYPE is non-NULL)  */
    2437                 :          98 :   if (otr_type && !useless_p () && !ctx.useless_p ())
    2438                 :             :     {
    2439                 :           0 :       restrict_to_inner_class (otr_type);
    2440                 :           0 :       ctx.restrict_to_inner_class (otr_type);
    2441                 :           0 :       if(invalid)
    2442                 :             :         return false;
    2443                 :             :     }
    2444                 :             : 
    2445                 :          98 :   if (equal_to (ctx))
    2446                 :             :     return false;
    2447                 :             : 
    2448                 :          61 :   if (ctx.useless_p () || invalid)
    2449                 :             :     {
    2450                 :           4 :       *this = ctx;
    2451                 :           4 :       return true;
    2452                 :             :     }
    2453                 :             : 
    2454                 :          57 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2455                 :             :     {
    2456                 :           0 :       fprintf (dump_file, "Polymorphic call context meet:");
    2457                 :           0 :       dump (dump_file);
    2458                 :           0 :       fprintf (dump_file, "With context:                    ");
    2459                 :           0 :       ctx.dump (dump_file);
    2460                 :           0 :       if (otr_type)
    2461                 :             :         {
    2462                 :           0 :           fprintf (dump_file, "To be used with type:            ");
    2463                 :           0 :           print_generic_expr (dump_file, otr_type, TDF_SLIM);
    2464                 :           0 :           fprintf (dump_file, "\n");
    2465                 :             :         }
    2466                 :             :     }
    2467                 :             : 
    2468                 :          57 :   if (!dynamic && ctx.dynamic)
    2469                 :             :     {
    2470                 :           7 :       dynamic = true;
    2471                 :           7 :       updated = true;
    2472                 :             :     }
    2473                 :             : 
    2474                 :             :   /* If call is known to be invalid, we are done.  */
    2475                 :          57 :   if (!outer_type)
    2476                 :             :     ;
    2477                 :          20 :   else if (!ctx.outer_type)
    2478                 :             :     {
    2479                 :           0 :       clear_outer_type ();
    2480                 :           0 :       updated = true;
    2481                 :             :     }
    2482                 :             :   /* If types are known to be same, merging is quite easy.  */
    2483                 :          20 :   else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
    2484                 :             :     {
    2485                 :          16 :       if (offset != ctx.offset
    2486                 :           0 :           && TYPE_SIZE (outer_type)
    2487                 :          16 :           && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
    2488                 :             :         {
    2489                 :           0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2490                 :           0 :             fprintf (dump_file, "Outer types match, offset mismatch -> clearing\n");
    2491                 :           0 :           clear_outer_type ();
    2492                 :           0 :           return true;
    2493                 :             :         }
    2494                 :          16 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2495                 :           0 :         fprintf (dump_file, "Outer types match, merging flags\n");
    2496                 :          16 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2497                 :             :         {
    2498                 :           0 :           updated = true;
    2499                 :           0 :           maybe_in_construction = true;
    2500                 :             :         }
    2501                 :          16 :       if (!maybe_derived_type && ctx.maybe_derived_type)
    2502                 :             :         {
    2503                 :           7 :           updated = true;
    2504                 :           7 :           maybe_derived_type = true;
    2505                 :             :         }
    2506                 :          16 :       if (!dynamic && ctx.dynamic)
    2507                 :             :         {
    2508                 :           0 :           updated = true;
    2509                 :           0 :           dynamic = true;
    2510                 :             :         }
    2511                 :             :     }
    2512                 :             :   /* See if one type contains the other as a field (not base).  */
    2513                 :           4 :   else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
    2514                 :             :                             outer_type, false, false))
    2515                 :             :     {
    2516                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2517                 :           0 :         fprintf (dump_file, "Second type contain the first as a field\n");
    2518                 :             : 
    2519                 :             :       /* The second type is more specified, so we keep the first.
    2520                 :             :          We need to set DYNAMIC flag to avoid declaring context INVALID
    2521                 :             :          of OFFSET ends up being out of range.  */
    2522                 :           0 :       if (!dynamic
    2523                 :           0 :           && (ctx.dynamic
    2524                 :           0 :               || (!otr_type
    2525                 :           0 :                   && (!TYPE_SIZE (ctx.outer_type)
    2526                 :           0 :                       || !TYPE_SIZE (outer_type)
    2527                 :           0 :                       || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
    2528                 :           0 :                                            TYPE_SIZE (outer_type), 0)))))
    2529                 :             :         {
    2530                 :           0 :           dynamic = true;
    2531                 :           0 :           updated = true;
    2532                 :             :         }
    2533                 :             :     }
    2534                 :           4 :   else if (contains_type_p (outer_type, offset - ctx.offset,
    2535                 :             :                             ctx.outer_type, false, false))
    2536                 :             :     {
    2537                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2538                 :           0 :         fprintf (dump_file, "First type contain the second as a field\n");
    2539                 :             : 
    2540                 :           0 :       if (!dynamic
    2541                 :           0 :           && (ctx.dynamic
    2542                 :           0 :               || (!otr_type
    2543                 :           0 :                   && (!TYPE_SIZE (ctx.outer_type)
    2544                 :           0 :                       || !TYPE_SIZE (outer_type)
    2545                 :           0 :                       || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
    2546                 :           0 :                                            TYPE_SIZE (outer_type), 0)))))
    2547                 :           0 :         dynamic = true;
    2548                 :           0 :       outer_type = ctx.outer_type;
    2549                 :           0 :       offset = ctx.offset;
    2550                 :           0 :       dynamic = ctx.dynamic;
    2551                 :           0 :       maybe_in_construction = ctx.maybe_in_construction;
    2552                 :           0 :       maybe_derived_type = ctx.maybe_derived_type;
    2553                 :           0 :       updated = true;
    2554                 :             :     }
    2555                 :             :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2556                 :           4 :   else if (contains_type_p (ctx.outer_type,
    2557                 :           4 :                             ctx.offset - offset, outer_type, false, true))
    2558                 :             :     {
    2559                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2560                 :           0 :         fprintf (dump_file, "First type is base of second\n");
    2561                 :           0 :       if (!maybe_derived_type)
    2562                 :             :         {
    2563                 :           0 :           maybe_derived_type = true;
    2564                 :           0 :           updated = true;
    2565                 :             :         }
    2566                 :           0 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2567                 :             :         {
    2568                 :           0 :           maybe_in_construction = true;
    2569                 :           0 :           updated = true;
    2570                 :             :         }
    2571                 :           0 :       if (!dynamic && ctx.dynamic)
    2572                 :             :         {
    2573                 :           0 :           dynamic = true;
    2574                 :           0 :           updated = true;
    2575                 :             :         }
    2576                 :             :     }
    2577                 :             :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2578                 :           4 :   else if (contains_type_p (outer_type,
    2579                 :           4 :                             offset - ctx.offset, ctx.outer_type, false, true))
    2580                 :             :     {
    2581                 :           4 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2582                 :           0 :         fprintf (dump_file, "Second type is base of first\n");
    2583                 :           4 :       outer_type = ctx.outer_type;
    2584                 :           4 :       offset = ctx.offset;
    2585                 :           4 :       updated = true;
    2586                 :           4 :       if (!maybe_derived_type)
    2587                 :           4 :         maybe_derived_type = true;
    2588                 :           4 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2589                 :           0 :         maybe_in_construction = true;
    2590                 :           4 :       if (!dynamic && ctx.dynamic)
    2591                 :           0 :         dynamic = true;
    2592                 :             :     }
    2593                 :             :   /* TODO handle merging using hierarchy. */
    2594                 :             :   else
    2595                 :             :     {
    2596                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2597                 :           0 :         fprintf (dump_file, "Giving up on meet\n");
    2598                 :           0 :       clear_outer_type ();
    2599                 :           0 :       updated = true;
    2600                 :             :     }
    2601                 :             : 
    2602                 :         114 :   updated |= meet_speculation_with (ctx.speculative_outer_type,
    2603                 :             :                                     ctx.speculative_offset,
    2604                 :          57 :                                     ctx.speculative_maybe_derived_type,
    2605                 :             :                                     otr_type);
    2606                 :             : 
    2607                 :          57 :   if (updated && dump_file && (dump_flags & TDF_DETAILS))
    2608                 :             :     {
    2609                 :           0 :       fprintf (dump_file, "Updated as:                      ");
    2610                 :           0 :       dump (dump_file);
    2611                 :           0 :       fprintf (dump_file, "\n");
    2612                 :             :     }
    2613                 :             :   return updated;
    2614                 :             : }
        

Generated by: LCOV version 2.1-beta

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