LCOV - code coverage report
Current view: top level - gcc - ipa-polymorphic-call.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.7 % 1205 996
Test Date: 2026-04-20 14:57:17 Functions: 96.6 % 29 28
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Analysis of polymorphic call context.
       2              :    Copyright (C) 2013-2026 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     37437184 : contains_polymorphic_type_p (const_tree type)
      54              : {
      55     42728415 :   type = TYPE_MAIN_VARIANT (type);
      56              : 
      57     42728415 :   if (RECORD_OR_UNION_TYPE_P (type))
      58              :     {
      59     10445906 :       if (TYPE_BINFO (type)
      60     10445906 :           && polymorphic_type_binfo_p (TYPE_BINFO (type)))
      61              :         return true;
      62    495574838 :       for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
      63    486741489 :         if (TREE_CODE (fld) == FIELD_DECL
      64     33445500 :             && !DECL_ARTIFICIAL (fld)
      65    517403398 :             && contains_polymorphic_type_p (TREE_TYPE (fld)))
      66              :           return true;
      67              :       return false;
      68              :     }
      69     32282509 :   if (TREE_CODE (type) == ARRAY_TYPE)
      70      5291231 :     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       135594 : possible_placement_new (tree type, tree expected_type,
      82              :                         HOST_WIDE_INT cur_offset)
      83              : {
      84       135594 :   if (cur_offset < 0)
      85              :     return true;
      86       132055 :   return ((TREE_CODE (type) != RECORD_TYPE
      87        20817 :            || !TYPE_BINFO (type)
      88        20851 :            || cur_offset >= POINTER_SIZE
      89        18513 :            || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
      90       152776 :           && (!TYPE_SIZE (type)
      91       131959 :               || !tree_fits_shwi_p (TYPE_SIZE (type))
      92       263918 :               || (cur_offset
      93       131959 :                   + (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
      94       121854 :                      : POINTER_SIZE)
      95       131959 :                   <= 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      2182599 : ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
     130              :                                                        bool consider_placement_new,
     131              :                                                        bool consider_bases)
     132              : {
     133      2182599 :   tree type = outer_type;
     134      2182599 :   HOST_WIDE_INT cur_offset = offset;
     135      2182599 :   bool speculative = false;
     136      2182599 :   bool size_unknown = false;
     137      2182599 :   unsigned HOST_WIDE_INT otr_type_size = POINTER_SIZE;
     138              : 
     139              :   /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set.  */
     140      2182599 :   if (!outer_type)
     141              :     {
     142        79062 :       clear_outer_type (otr_type);
     143        79062 :       type = otr_type;
     144        79062 :       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      2103537 :   else if (TYPE_SIZE (outer_type)
     156      2103514 :            && tree_fits_shwi_p (TYPE_SIZE (outer_type))
     157      2103514 :            && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
     158      4207051 :            && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
     159              :    {
     160         4341 :      bool der = maybe_derived_type; /* clear_outer_type will reset it.  */
     161         4341 :      bool dyn = dynamic;
     162         4341 :      clear_outer_type (otr_type);
     163         4341 :      type = otr_type;
     164         4341 :      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         4341 :      if (!der && !dyn)
     171              :        {
     172         2721 :          clear_speculation ();
     173         2721 :          invalid = true;
     174         2721 :          return false;
     175              :        }
     176              :    }
     177              : 
     178      2053992 :   if (otr_type && TYPE_SIZE (otr_type)
     179      4233865 :       && tree_fits_shwi_p (TYPE_SIZE (otr_type)))
     180      2053987 :     otr_type_size = tree_to_uhwi (TYPE_SIZE (otr_type));
     181              : 
     182      2179878 :   if (!type || offset < 0)
     183         3539 :     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      2791159 :   while (true)
     191              :     {
     192      2791159 :       unsigned HOST_WIDE_INT pos, size;
     193      2791159 :       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      2791159 :       if (TYPE_SIZE (type)
     200      2791136 :           && tree_fits_shwi_p (TYPE_SIZE (type))
     201      5582295 :           && 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      2791159 :       if ((otr_type
     208      2376644 :            && types_odr_comparable (type, otr_type)
     209      2376644 :            && types_same_for_odr (type, otr_type))
     210      2791159 :           || (!otr_type
     211       414515 :               && TREE_CODE (type) == RECORD_TYPE
     212       313061 :               && TYPE_BINFO (type)
     213       312286 :               && polymorphic_type_binfo_p (TYPE_BINFO (type))))
     214              :         {
     215      1674057 :           if (speculative)
     216              :             {
     217              :               /* If we did not match the offset, just give up on speculation.  */
     218         9582 :               if (cur_offset != 0
     219              :                   /* Also check if speculation did not end up being same as
     220              :                      non-speculation.  */
     221         9582 :                   || (types_must_be_same_for_odr (speculative_outer_type,
     222              :                                                   outer_type)
     223           38 :                       && (maybe_derived_type
     224           38 :                           == speculative_maybe_derived_type)))
     225            0 :                 clear_speculation ();
     226         9582 :               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      1661994 :               if (otr_type && TREE_CODE (outer_type) == RECORD_TYPE
     233      1661994 :                   && (!in_lto_p || odr_type_p (outer_type))
     234      1661994 :                   && type_with_linkage_p (outer_type)
     235      3326469 :                   && type_known_to_have_no_derivations_p (outer_type))
     236         8632 :                 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      1664475 :               if (cur_offset != 0)
     244         1957 :                 goto no_useful_type_info;
     245              :               /* If we determined type precisely or we have no clue on
     246              :                  speculation, we are done.  */
     247      1298179 :               if (!maybe_derived_type || !speculative_outer_type
     248      1742914 :                   || !speculation_consistent_p (speculative_outer_type,
     249              :                                                 speculative_offset,
     250              :                                                 speculative_maybe_derived_type,
     251              :                                                 otr_type))
     252              :                 {
     253      1652940 :                   clear_speculation ();
     254      1652940 :                   return true;
     255              :                 }
     256              :               /* Otherwise look into speculation now.  */
     257              :               else
     258              :                 {
     259         9578 :                   speculative = true;
     260         9578 :                   type = speculative_outer_type;
     261         9578 :                   cur_offset = speculative_offset;
     262         9578 :                   continue;
     263              :                 }
     264              :             }
     265              :         }
     266              : 
     267              :       /* Walk fields and find corresponding on at OFFSET.  */
     268      1117102 :       if (TREE_CODE (type) == RECORD_TYPE)
     269              :         {
     270     15703292 :           for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
     271              :             {
     272     29254670 :               if (TREE_CODE (fld) != FIELD_DECL
     273     15440208 :                   || TREE_TYPE (fld) == error_mark_node)
     274     13814462 :                 continue;
     275              : 
     276      1625746 :               pos = int_bit_position (fld);
     277      1625746 :               if (pos > (unsigned HOST_WIDE_INT)cur_offset)
     278       406336 :                 continue;
     279              : 
     280              :               /* Do not consider vptr itself.  Not even for placement new.  */
     281      1184693 :               if (!pos && DECL_ARTIFICIAL (fld)
     282       932963 :                   && POINTER_TYPE_P (TREE_TYPE (fld))
     283       179173 :                   && TYPE_BINFO (type)
     284      1398583 :                   && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     285       179173 :                 continue;
     286              : 
     287      1040237 :               if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
     288            0 :                 goto no_useful_type_info;
     289      1040237 :               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      1040237 :               if (pos <= (unsigned HOST_WIDE_INT)cur_offset
     301      2080474 :                   && (pos + size) >= (unsigned HOST_WIDE_INT)cur_offset
     302      1062473 :                                      + POINTER_SIZE
     303       807906 :                   && (!otr_type
     304       515769 :                       || !TYPE_SIZE (TREE_TYPE (fld))
     305       515769 :                       || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld)))
     306       515769 :                       || (pos + tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld))))
     307       515769 :                           >= cur_offset + otr_type_size))
     308              :                 break;
     309              :             }
     310              : 
     311      1005514 :           if (!fld)
     312       263084 :             goto no_useful_type_info;
     313              : 
     314       742430 :           type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
     315       742430 :           cur_offset -= pos;
     316              :           /* DECL_ARTIFICIAL represents a basetype.  */
     317       742430 :           if (!DECL_ARTIFICIAL (fld))
     318              :             {
     319       261696 :               if (!speculative)
     320              :                 {
     321       261300 :                   outer_type = type;
     322       261300 :                   offset = cur_offset;
     323              :                   /* As soon as we see an field containing the type,
     324              :                      we know we are not looking for derivations.  */
     325       261300 :                   maybe_derived_type = false;
     326              :                 }
     327              :               else
     328              :                 {
     329          396 :                   speculative_outer_type = type;
     330          396 :                   speculative_offset = cur_offset;
     331          396 :                   speculative_maybe_derived_type = false;
     332              :                 }
     333              :             }
     334       480734 :           else if (!consider_bases)
     335       137218 :             goto no_useful_type_info;
     336              :         }
     337       111588 :       else if (TREE_CODE (type) == ARRAY_TYPE)
     338              :         {
     339         9850 :           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         9850 :           if (!TYPE_SIZE (subtype)
     345         9850 :               || !tree_fits_shwi_p (TYPE_SIZE (subtype))
     346         9850 :               || tree_to_shwi (TYPE_SIZE (subtype)) <= 0
     347        19700 :               || !contains_polymorphic_type_p (subtype))
     348         9467 :             goto no_useful_type_info;
     349              : 
     350          383 :           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          383 :           if (TYPE_SIZE (subtype)
     355          383 :               && (cur_offset + otr_type_size
     356          383 :                   > tree_to_uhwi (TYPE_SIZE (subtype))))
     357          357 :             goto no_useful_type_info;
     358              : 
     359           26 :           cur_offset = new_offset;
     360           26 :           type = TYPE_MAIN_VARIANT (subtype);
     361           26 :           if (!speculative)
     362              :             {
     363           26 :               outer_type = type;
     364           26 :               offset = cur_offset;
     365           26 :               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       101738 : no_useful_type_info:
     378          336 :           if (maybe_derived_type && !speculative
     379          336 :               && TREE_CODE (outer_type) == RECORD_TYPE
     380          336 :               && TREE_CODE (otr_type) == RECORD_TYPE
     381          336 :               && TYPE_BINFO (otr_type)
     382          336 :               && !offset
     383       517696 :               && get_binfo_at_offset (TYPE_BINFO (otr_type), 0, outer_type))
     384              :             {
     385          336 :               clear_outer_type (otr_type);
     386          336 :               if (!speculative_outer_type
     387          336 :                   || !speculation_consistent_p (speculative_outer_type,
     388              :                                                 speculative_offset,
     389            0 :                                                 speculative_maybe_derived_type,
     390              :                                                 otr_type))
     391          336 :                 clear_speculation ();
     392          336 :               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       517024 :           if (!speculative
     405       517024 :               && consider_placement_new
     406       517024 :               && (size_unknown || !type || maybe_derived_type
     407       135594 :                   || 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       134508 :               if (!speculative)
     416              :                 {
     417       134508 :                   clear_outer_type (otr_type);
     418       134508 :                   if (!speculative_outer_type
     419       134514 :                       || !speculation_consistent_p (speculative_outer_type,
     420              :                                                     speculative_offset,
     421            6 :                                                     speculative_maybe_derived_type,
     422              :                                                     otr_type))
     423       134504 :                     clear_speculation ();
     424       134508 :                   if (speculative_outer_type)
     425              :                     {
     426            4 :                       speculative = true;
     427            4 :                       type = speculative_outer_type;
     428            4 :                       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       382516 :               clear_speculation ();
     442       382516 :               if (speculative)
     443              :                 return true;
     444       382516 :               clear_outer_type (otr_type);
     445       382516 :               invalid = true;
     446       382516 :               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       708379 : 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       708379 :   ipa_polymorphic_call_context context;
     465              : 
     466              :   /* Check that type is within range.  */
     467       708379 :   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       702100 :   context.offset = offset;
     477       702100 :   context.outer_type = TYPE_MAIN_VARIANT (outer_type);
     478       702100 :   context.maybe_derived_type = false;
     479       702100 :   context.dynamic = false;
     480       702100 :   return context.restrict_to_inner_class (otr_type, consider_placement_new,
     481       702100 :                                           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     65367046 : polymorphic_ctor_dtor_p (tree fn, bool check_clones)
     490              : {
     491     65367046 :   if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
     492    108314420 :       || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
     493              :     {
     494     47028791 :       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     46982497 :       fn = DECL_ABSTRACT_ORIGIN (fn);
     500     46982497 :       if (!fn
     501     34112383 :           || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
     502     68552170 :           || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
     503     46982154 :         return NULL_TREE;
     504              :     }
     505              : 
     506              :   /* We used to check that the ctor/dtor is not pure/const.
     507              :      However this may interact with pass ordering.  It is possible that the
     508              :      store of vtable is optimized out in offline copy, but inline copies keep
     509              :      it and then local-pure-const overwrites the flag.  See PR120098.  */
     510              : 
     511              :   return fn;
     512              : }
     513              : 
     514              : /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
     515              :    If CHECK_CLONES is true, also check for clones of ctor/dtors.  */
     516              : 
     517              : tree
     518    180712707 : inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
     519              : {
     520    180712707 :   tree fn = block_ultimate_origin (block);
     521    180712707 :   if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
     522              :     return NULL_TREE;
     523              : 
     524     53729369 :   return polymorphic_ctor_dtor_p (fn, check_clones);
     525              : }
     526              : 
     527              : 
     528              : /* We know that the instance is stored in variable or parameter
     529              :    (not dynamically allocated) and we want to disprove the fact
     530              :    that it may be in construction at invocation of CALL.
     531              : 
     532              :    BASE represents memory location where instance is stored.
     533              :    If BASE is NULL, it is assumed to be global memory.
     534              :    OUTER_TYPE is known type of the instance or NULL if not
     535              :    known.
     536              : 
     537              :    For the variable to be in construction we actually need to
     538              :    be in constructor of corresponding global variable or
     539              :    the inline stack of CALL must contain the constructor.
     540              :    Check this condition.  This check works safely only before
     541              :    IPA passes, because inline stacks may become out of date
     542              :    later.  */
     543              : 
     544              : bool
     545     29713514 : decl_maybe_in_construction_p (tree base, tree outer_type,
     546              :                               gimple *call, tree function)
     547              : {
     548     29713514 :   if (outer_type)
     549        47628 :     outer_type = TYPE_MAIN_VARIANT (outer_type);
     550     29713514 :   gcc_assert (!base || DECL_P (base));
     551              : 
     552              :   /* After inlining the code unification optimizations may invalidate
     553              :      inline stacks.  Also we need to give up on global variables after
     554              :      IPA, because addresses of these may have been propagated to their
     555              :      constructors.  */
     556     29713514 :   if (DECL_STRUCT_FUNCTION (function)->after_inlining)
     557              :     return true;
     558              : 
     559              :   /* Pure functions cannot do any changes on the dynamic type;
     560              :      that require writing to memory.  */
     561        38600 :   if ((!base || !auto_var_in_fn_p (base, function))
     562     29678042 :       && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
     563              :     return false;
     564              : 
     565     29345186 :   bool check_clones = !base || is_global_var (base);
     566    153960982 :   for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
     567     62307898 :        block = BLOCK_SUPERCONTEXT (block))
     568     62335118 :     if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones))
     569              :       {
     570       348359 :         tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
     571              : 
     572       348359 :         if (!outer_type || !types_odr_comparable (type, outer_type))
     573              :           {
     574       339866 :             if (TREE_CODE (type) == RECORD_TYPE
     575       338422 :                 && TYPE_BINFO (type)
     576       675690 :                 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     577              :               return true;
     578              :           }
     579         8493 :         else if (types_same_for_odr (type, outer_type))
     580              :           return true;
     581              :       }
     582              : 
     583     29317966 :   if (!base || (VAR_P (base) && is_global_var (base)))
     584              :     {
     585     29291234 :       if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
     586     37263221 :           || (!DECL_CXX_CONSTRUCTOR_P (function)
     587      6698593 :               && !DECL_CXX_DESTRUCTOR_P (function)))
     588              :         {
     589     27495419 :           if (!DECL_ABSTRACT_ORIGIN (function))
     590              :             return false;
     591              :           /* Watch for clones where we constant propagated the first
     592              :              argument (pointer to the instance).  */
     593        89477 :           function = DECL_ABSTRACT_ORIGIN (function);
     594        89477 :           if (!function
     595        89477 :               || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
     596       141961 :               || (!DECL_CXX_CONSTRUCTOR_P (function)
     597        52452 :                   && !DECL_CXX_DESTRUCTOR_P (function)))
     598              :             return false;
     599              :         }
     600      1795847 :       tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (function));
     601      1795847 :       if (!outer_type || !types_odr_comparable (type, outer_type))
     602              :         {
     603      1795811 :           if (TREE_CODE (type) == RECORD_TYPE
     604      1794466 :               && TYPE_BINFO (type)
     605      3581132 :               && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     606              :             return true;
     607              :         }
     608           36 :       else if (types_same_for_odr (type, outer_type))
     609              :         return true;
     610              :     }
     611              :   return false;
     612              : }
     613              : 
     614              : /* Dump human readable context to F.  If NEWLINE is true, it will be terminated
     615              :    by a newline.  */
     616              : 
     617              : void
     618         1411 : ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
     619              : {
     620         1411 :   fprintf (f, "    ");
     621         1411 :   if (invalid)
     622            0 :     fprintf (f, "Call is known to be undefined");
     623              :   else
     624              :     {
     625         1411 :       if (useless_p ())
     626            1 :         fprintf (f, "nothing known");
     627         1411 :       if (outer_type || offset)
     628              :         {
     629         1600 :           fprintf (f, "Outer type%s:", dynamic ? " (dynamic)" : "");
     630         1247 :           print_generic_expr (f, outer_type, TDF_SLIM);
     631         1247 :           if (maybe_derived_type)
     632          737 :             fprintf (f, " (or a derived type)");
     633         1247 :           if (maybe_in_construction)
     634          190 :             fprintf (f, " (maybe in construction)");
     635         1247 :           fprintf (f, " offset " HOST_WIDE_INT_PRINT_DEC,
     636         1247 :                    offset);
     637              :         }
     638         1411 :       if (speculative_outer_type)
     639              :         {
     640          306 :           if (outer_type || offset)
     641          143 :             fprintf (f, " ");
     642          306 :           fprintf (f, "Speculative outer type:");
     643          306 :           print_generic_expr (f, speculative_outer_type, TDF_SLIM);
     644          306 :           if (speculative_maybe_derived_type)
     645          273 :             fprintf (f, " (or a derived type)");
     646          306 :           fprintf (f, " at offset " HOST_WIDE_INT_PRINT_DEC,
     647          306 :                    speculative_offset);
     648              :         }
     649              :     }
     650         1411 :   if (newline)
     651          685 :     fprintf(f, "\n");
     652         1411 : }
     653              : 
     654              : /* Print context to stderr.  */
     655              : 
     656              : void
     657            0 : ipa_polymorphic_call_context::debug () const
     658              : {
     659            0 :   dump (stderr);
     660            0 : }
     661              : 
     662              : /* Stream out the context to OB.  */
     663              : 
     664              : void
     665         4763 : ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
     666              : {
     667         4763 :   struct bitpack_d bp = bitpack_create (ob->main_stream);
     668              : 
     669         4763 :   bp_pack_value (&bp, invalid, 1);
     670         4763 :   bp_pack_value (&bp, maybe_in_construction, 1);
     671         4763 :   bp_pack_value (&bp, maybe_derived_type, 1);
     672         4763 :   bp_pack_value (&bp, speculative_maybe_derived_type, 1);
     673         4763 :   bp_pack_value (&bp, dynamic, 1);
     674         4763 :   bp_pack_value (&bp, outer_type != NULL, 1);
     675         4763 :   bp_pack_value (&bp, offset != 0, 1);
     676         4763 :   bp_pack_value (&bp, speculative_outer_type != NULL, 1);
     677         4763 :   streamer_write_bitpack (&bp);
     678              : 
     679         4763 :   if (outer_type != NULL)
     680         2330 :     stream_write_tree (ob, outer_type, true);
     681         4763 :   if (offset)
     682          559 :     streamer_write_hwi (ob, offset);
     683         4763 :   if (speculative_outer_type != NULL)
     684              :     {
     685         1727 :       stream_write_tree (ob, speculative_outer_type, true);
     686         1727 :       streamer_write_hwi (ob, speculative_offset);
     687              :     }
     688              :   else
     689         3036 :     gcc_assert (!speculative_offset);
     690         4763 : }
     691              : 
     692              : /* Stream in the context from IB and DATA_IN.  */
     693              : 
     694              : void
     695         1524 : ipa_polymorphic_call_context::stream_in (class lto_input_block *ib,
     696              :                                          class data_in *data_in)
     697              : {
     698         1524 :   struct bitpack_d bp = streamer_read_bitpack (ib);
     699              : 
     700         1524 :   invalid = bp_unpack_value (&bp, 1);
     701         1524 :   maybe_in_construction = bp_unpack_value (&bp, 1);
     702         1524 :   maybe_derived_type = bp_unpack_value (&bp, 1);
     703         1524 :   speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
     704         1524 :   dynamic = bp_unpack_value (&bp, 1);
     705         1524 :   bool outer_type_p = bp_unpack_value (&bp, 1);
     706         1524 :   bool offset_p = bp_unpack_value (&bp, 1);
     707         1524 :   bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
     708              : 
     709         1524 :   if (outer_type_p)
     710          744 :     outer_type = stream_read_tree (ib, data_in);
     711              :   else
     712          780 :     outer_type = NULL;
     713         1524 :   if (offset_p)
     714          396 :     offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
     715              :   else
     716         1128 :     offset = 0;
     717         1524 :   if (speculative_outer_type_p)
     718              :     {
     719          548 :       speculative_outer_type = stream_read_tree (ib, data_in);
     720          548 :       speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
     721              :     }
     722              :   else
     723              :     {
     724          976 :       speculative_outer_type = NULL;
     725          976 :       speculative_offset = 0;
     726              :     }
     727         1524 : }
     728              : 
     729              : /* Produce polymorphic call context for call method of instance
     730              :    that is located within BASE (that is assumed to be a decl) at offset OFF. */
     731              : 
     732              : void
     733      1277690 : ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off)
     734              : {
     735      1277690 :   gcc_assert (DECL_P (base));
     736      1277690 :   clear_speculation ();
     737              : 
     738      1277690 :   if (!contains_polymorphic_type_p (TREE_TYPE (base)))
     739              :     {
     740      1228927 :       clear_outer_type ();
     741      1228927 :       offset = off;
     742      1228927 :       return;
     743              :     }
     744        48763 :   outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
     745        48763 :   offset = off;
     746              :   /* Make very conservative assumption that all objects
     747              :      may be in construction.
     748              : 
     749              :      It is up to caller to revisit this via
     750              :      get_dynamic_type or decl_maybe_in_construction_p.  */
     751        48763 :   maybe_in_construction = true;
     752        48763 :   maybe_derived_type = false;
     753        48763 :   dynamic = false;
     754              : }
     755              : 
     756              : /* CST is an invariant (address of decl), try to get meaningful
     757              :    polymorphic call context for polymorphic call of method
     758              :    if instance of OTR_TYPE that is located at offset OFF of this invariant.
     759              :    Return FALSE if nothing meaningful can be found.  */
     760              : 
     761              : bool
     762        12011 : ipa_polymorphic_call_context::set_by_invariant (tree cst,
     763              :                                                 tree otr_type,
     764              :                                                 HOST_WIDE_INT off)
     765              : {
     766        12011 :   poly_int64 offset2, size, max_size;
     767        12011 :   bool reverse;
     768        12011 :   tree base;
     769              : 
     770        12011 :   invalid = false;
     771        12011 :   clear_outer_type (otr_type);
     772              : 
     773        12011 :   if (TREE_CODE (cst) != ADDR_EXPR)
     774              :     return false;
     775              : 
     776         2669 :   cst = TREE_OPERAND (cst, 0);
     777         2669 :   base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
     778         2669 :   if (!DECL_P (base) || !known_size_p (max_size) || maybe_ne (max_size, size))
     779              :     return false;
     780              : 
     781              :   /* Only type inconsistent programs can have otr_type that is
     782              :      not part of outer type.  */
     783         2660 :   if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type))
     784              :     return false;
     785              : 
     786         2660 :   set_by_decl (base, off);
     787         2660 :   return true;
     788              : }
     789              : 
     790              : /* See if OP is SSA name initialized as a copy or by single assignment.
     791              :    If so, walk the SSA graph up.  Because simple PHI conditional is considered
     792              :    copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
     793              :    graph.  */
     794              : 
     795              : static tree
     796      6894547 : walk_ssa_copies (tree op, hash_set<tree> **global_visited = NULL)
     797              : {
     798      6894547 :   hash_set <tree> *visited = NULL;
     799      6894547 :   STRIP_NOPS (op);
     800      6894547 :   while (TREE_CODE (op) == SSA_NAME
     801      3379638 :          && !SSA_NAME_IS_DEFAULT_DEF (op)
     802              :          /* We might be called via fold_stmt during cfgcleanup where
     803              :             SSA form need not be up-to-date.  */
     804      2326501 :          && !name_registered_for_update_p (op)
     805      9671361 :          && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
     806       499381 :              || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
     807              :     {
     808      1980586 :       if (global_visited)
     809              :         {
     810      1310682 :           if (!*global_visited)
     811      1229106 :             *global_visited = new hash_set<tree>;
     812      1310682 :           if ((*global_visited)->add (op))
     813            0 :             goto done;
     814              :         }
     815              :       else
     816              :         {
     817       669904 :           if (!visited)
     818       649870 :             visited = new hash_set<tree>;
     819       669904 :           if (visited->add (op))
     820            0 :             goto done;
     821              :         }
     822              :       /* Special case
     823              :          if (ptr == 0)
     824              :            ptr = 0;
     825              :          else
     826              :            ptr = ptr.foo;
     827              :          This pattern is implicitly produced for casts to non-primary
     828              :          bases.  When doing context analysis, we do not really care
     829              :          about the case pointer is NULL, because the call will be
     830              :          undefined anyway.  */
     831      1980586 :       if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
     832              :         {
     833       153466 :           gimple *phi = SSA_NAME_DEF_STMT (op);
     834              : 
     835       153466 :           if (gimple_phi_num_args (phi) > 2)
     836        33263 :             goto done;
     837       120203 :           if (gimple_phi_num_args (phi) == 1)
     838          812 :             op = gimple_phi_arg_def (phi, 0);
     839       119391 :           else if (integer_zerop (gimple_phi_arg_def (phi, 0)))
     840         5161 :             op = gimple_phi_arg_def (phi, 1);
     841       114230 :           else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
     842        22411 :             op = gimple_phi_arg_def (phi, 0);
     843              :           else
     844        91819 :             goto done;
     845              :         }
     846              :       else
     847              :         {
     848      1827120 :           if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
     849      1405191 :             goto done;
     850       421929 :           op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
     851              :         }
     852       450313 :       STRIP_NOPS (op);
     853              :     }
     854      6894547 : done:
     855      6894547 :   if (visited)
     856       649870 :     delete (visited);
     857      6894547 :   return op;
     858              : }
     859              : 
     860              : /* Create polymorphic call context from IP invariant CST.
     861              :    This is typically &global_var.
     862              :    OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
     863              :    is offset of call.  */
     864              : 
     865        12011 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst,
     866              :                                                             tree otr_type,
     867        12011 :                                                             HOST_WIDE_INT off)
     868              : {
     869        12011 :   clear_speculation ();
     870        12011 :   set_by_invariant (cst, otr_type, off);
     871        12011 : }
     872              : 
     873              : /* Build context for pointer REF contained in FNDECL at statement STMT.
     874              :    if INSTANCE is non-NULL, return pointer to the object described by
     875              :    the context or DECL where context is contained in.  */
     876              : 
     877      4121307 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
     878              :                                                             tree ref,
     879              :                                                             gimple *stmt,
     880      4121307 :                                                             tree *instance)
     881              : {
     882      4121307 :   tree otr_type = NULL;
     883      4121307 :   tree base_pointer;
     884      4121307 :   hash_set <tree> *visited = NULL;
     885              : 
     886      4121307 :   if (TREE_CODE (ref) == OBJ_TYPE_REF)
     887              :     {
     888       905089 :       otr_type = obj_type_ref_class (ref);
     889       905089 :       base_pointer = OBJ_TYPE_REF_OBJECT (ref);
     890              :     }
     891              :   else
     892              :     base_pointer = ref;
     893              : 
     894              :   /* Set up basic info in case we find nothing interesting in the analysis.  */
     895      4121307 :   clear_speculation ();
     896      4121307 :   clear_outer_type (otr_type);
     897      4121307 :   invalid = false;
     898              : 
     899              :   /* Walk SSA for outer object.  */
     900      4398428 :   while (true)
     901              :     {
     902      4398428 :       base_pointer = walk_ssa_copies (base_pointer, &visited);
     903      4398428 :       if (TREE_CODE (base_pointer) == ADDR_EXPR)
     904              :         {
     905      1983760 :           HOST_WIDE_INT offset2, size;
     906      1983760 :           bool reverse;
     907      1983760 :           tree base
     908      1983760 :             = get_ref_base_and_extent_hwi (TREE_OPERAND (base_pointer, 0),
     909              :                                            &offset2, &size, &reverse);
     910      1983760 :           if (!base)
     911              :             break;
     912              : 
     913      1960646 :           combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
     914      1960646 :                                     offset + offset2,
     915              :                                     true,
     916              :                                     NULL /* Do not change outer type.  */);
     917              : 
     918              :           /* If this is a varying address, punt.  */
     919      1960646 :           if (TREE_CODE (base) == MEM_REF || DECL_P (base))
     920              :             {
     921              :               /* We found dereference of a pointer.  Type of the pointer
     922              :                  and MEM_REF is meaningless, but we can look further.  */
     923      1552159 :               offset_int mem_offset;
     924      1552159 :               if (TREE_CODE (base) == MEM_REF
     925      1552159 :                   && mem_ref_offset (base).is_constant (&mem_offset))
     926              :                 {
     927       277129 :                   offset_int o = mem_offset * BITS_PER_UNIT;
     928       277129 :                   o += offset;
     929       277129 :                   o += offset2;
     930       277129 :                   if (!wi::fits_shwi_p (o))
     931              :                     break;
     932       277121 :                   base_pointer = TREE_OPERAND (base, 0);
     933       277121 :                   offset = o.to_shwi ();
     934       277121 :                   outer_type = NULL;
     935              :                 }
     936              :               /* We found base object.  In this case the outer_type
     937              :                  is known.  */
     938      1275030 :               else if (DECL_P (base))
     939              :                 {
     940      1275030 :                   if (visited)
     941          712 :                     delete (visited);
     942              :                   /* Only type inconsistent programs can have otr_type that is
     943              :                      not part of outer type.  */
     944      1275030 :                   if (otr_type
     945      1289223 :                       && !contains_type_p (TREE_TYPE (base),
     946        14193 :                                            offset + offset2, otr_type))
     947              :                     {
     948            0 :                       invalid = true;
     949            0 :                       if (instance)
     950            0 :                         *instance = base_pointer;
     951      1275030 :                       return;
     952              :                     }
     953      1275030 :                   set_by_decl (base, offset + offset2);
     954      1275030 :                   if (outer_type && maybe_in_construction && stmt)
     955        47628 :                     maybe_in_construction
     956        47628 :                      = decl_maybe_in_construction_p (base,
     957              :                                                      outer_type,
     958              :                                                      stmt,
     959              :                                                      fndecl);
     960      1275030 :                   if (instance)
     961      1264801 :                     *instance = base;
     962      1275030 :                   return;
     963              :                 }
     964              :               else
     965              :                 break;
     966              :             }
     967              :           else
     968              :             break;
     969              :         }
     970      2414668 :       else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
     971      2414668 :                && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
     972              :         {
     973            0 :           offset_int o
     974            0 :             = offset_int::from (wi::to_wide (TREE_OPERAND (base_pointer, 1)),
     975              :                                 SIGNED);
     976            0 :           o *= BITS_PER_UNIT;
     977            0 :           o += offset;
     978            0 :           if (!wi::fits_shwi_p (o))
     979              :             break;
     980            0 :           offset = o.to_shwi ();
     981            0 :           base_pointer = TREE_OPERAND (base_pointer, 0);
     982              :         }
     983              :       else
     984              :         break;
     985              :     }
     986              : 
     987      2846277 :   if (visited)
     988      1228394 :     delete (visited);
     989              : 
     990              :   /* Try to determine type of the outer object.  */
     991      2846277 :   if (TREE_CODE (base_pointer) == SSA_NAME
     992      2311626 :       && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
     993      3856360 :       && TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL)
     994              :     {
     995              :       /* See if parameter is THIS pointer of a method.  */
     996       998436 :       if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
     997      1554716 :           && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
     998              :         {
     999       427473 :           outer_type
    1000       427473 :              = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
    1001       427473 :           cgraph_node *node = cgraph_node::get (current_function_decl);
    1002       427473 :           gcc_assert (TREE_CODE (outer_type) == RECORD_TYPE
    1003              :                       || TREE_CODE (outer_type) == UNION_TYPE);
    1004              : 
    1005              :           /* Handle the case we inlined into a thunk.  In this case
    1006              :              thunk has THIS pointer of type bar, but it really receives
    1007              :              address to its base type foo which sits in bar at
    1008              :              0-thunk.fixed_offset.  It starts with code that adds
    1009              :              think.fixed_offset to the pointer to compensate for this.
    1010              : 
    1011              :              Because we walked all the way to the beginning of thunk, we now
    1012              :              see pointer &bar-thunk.fixed_offset and need to compensate
    1013              :              for it.  */
    1014       427473 :           thunk_info *info = thunk_info::get (node);
    1015       427473 :           if (info && info->fixed_offset)
    1016            7 :             offset -= info->fixed_offset * BITS_PER_UNIT;
    1017              : 
    1018              :           /* Dynamic casting has possibly upcasted the type
    1019              :              in the hierarchy.  In this case outer type is less
    1020              :              informative than inner type and we should forget
    1021              :              about it.  */
    1022       427473 :           if ((otr_type
    1023       158560 :                && !contains_type_p (outer_type, offset,
    1024              :                                     otr_type))
    1025       425440 :               || !contains_polymorphic_type_p (outer_type)
    1026              :               /* If we compile thunk with virtual offset, the THIS pointer
    1027              :                  is adjusted by unknown value.  We can't thus use outer info
    1028              :                  at all.  */
    1029       645344 :               || (info && info->virtual_offset_p))
    1030              :             {
    1031       209602 :               outer_type = NULL;
    1032       209602 :               if (instance)
    1033       207868 :                 *instance = base_pointer;
    1034       209602 :               return;
    1035              :             }
    1036              : 
    1037       217871 :           dynamic = true;
    1038              : 
    1039              :           /* If the function is constructor or destructor, then
    1040              :              the type is possibly in construction, but we know
    1041              :              it is not derived type.  */
    1042       217871 :           if (DECL_CXX_CONSTRUCTOR_P (fndecl)
    1043       217871 :               || DECL_CXX_DESTRUCTOR_P (fndecl))
    1044              :             {
    1045        31307 :               maybe_in_construction = true;
    1046        31307 :               maybe_derived_type = false;
    1047              :             }
    1048              :           else
    1049              :             {
    1050       186564 :               maybe_derived_type = true;
    1051       186564 :               maybe_in_construction = false;
    1052              :             }
    1053       217871 :           if (instance)
    1054              :             {
    1055        97699 :               thunk_info *info = thunk_info::get (node);
    1056              :               /* If method is expanded thunk, we need to apply thunk offset
    1057              :                  to instance pointer.  */
    1058        97699 :               if (info && (info->virtual_offset_p || info->fixed_offset))
    1059            5 :                 *instance = NULL;
    1060              :               else
    1061        97694 :                 *instance = base_pointer;
    1062              :             }
    1063       217871 :           return;
    1064              :         }
    1065              :       /* Non-PODs passed by value are really passed by invisible
    1066              :          reference.  In this case we also know the type of the
    1067              :          object.  */
    1068       570963 :       if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
    1069              :         {
    1070        19543 :           outer_type
    1071        19543 :              = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
    1072              :           /* Only type inconsistent programs can have otr_type that is
    1073              :              not part of outer type.  */
    1074        19543 :           if (otr_type && !contains_type_p (outer_type, offset,
    1075              :                                             otr_type))
    1076              :             {
    1077            0 :               invalid = true;
    1078            0 :               if (instance)
    1079            0 :                 *instance = base_pointer;
    1080            0 :               return;
    1081              :             }
    1082              :           /* Non-polymorphic types have no interest for us.  */
    1083        19543 :           else if (!otr_type && !contains_polymorphic_type_p (outer_type))
    1084              :             {
    1085        19455 :               outer_type = NULL;
    1086        19455 :               if (instance)
    1087        19455 :                 *instance = base_pointer;
    1088        19455 :               return;
    1089              :             }
    1090           88 :           maybe_derived_type = false;
    1091           88 :           maybe_in_construction = false;
    1092           88 :           if (instance)
    1093           69 :             *instance = base_pointer;
    1094           88 :           return;
    1095              :         }
    1096              :     }
    1097              : 
    1098      2399261 :   tree base_type = TREE_TYPE (base_pointer);
    1099              : 
    1100      2399261 :   if (TREE_CODE (base_pointer) == SSA_NAME
    1101      1864610 :       && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
    1102      2962328 :       && !(TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL
    1103        11647 :            || TREE_CODE (SSA_NAME_VAR (base_pointer)) == RESULT_DECL))
    1104              :     {
    1105          352 :       invalid = true;
    1106          352 :       if (instance)
    1107          236 :         *instance = base_pointer;
    1108          352 :       return;
    1109              :     }
    1110      2398909 :   if (TREE_CODE (base_pointer) == SSA_NAME
    1111      1864258 :       && SSA_NAME_DEF_STMT (base_pointer)
    1112      4263167 :       && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer)))
    1113       902110 :     base_type = TREE_TYPE (gimple_assign_rhs1
    1114              :                             (SSA_NAME_DEF_STMT (base_pointer)));
    1115              : 
    1116      2398909 :   if (base_type && POINTER_TYPE_P (base_type))
    1117      2398909 :     combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)),
    1118              :                               offset,
    1119              :                               true, NULL /* Do not change type here */);
    1120              :   /* TODO: There are multiple ways to derive a type.  For instance
    1121              :      if BASE_POINTER is passed to an constructor call prior our reference.
    1122              :      We do not make this type of flow sensitive analysis yet.  */
    1123      2398909 :   if (instance)
    1124      1831498 :     *instance = base_pointer;
    1125              :   return;
    1126              : }
    1127              : 
    1128              : /* Structure to be passed in between detect_type_change and
    1129              :    check_stmt_for_type_change.  */
    1130              : 
    1131              : struct type_change_info
    1132              : {
    1133              :   /* Offset into the object where there is the virtual method pointer we are
    1134              :      looking for.  */
    1135              :   HOST_WIDE_INT offset;
    1136              :   /* The declaration or SSA_NAME pointer of the base that we are checking for
    1137              :      type change.  */
    1138              :   tree instance;
    1139              :   /* The reference to virtual table pointer used.  */
    1140              :   tree vtbl_ptr_ref;
    1141              :   tree otr_type;
    1142              :   /* If we actually can tell the type that the object has changed to, it is
    1143              :      stored in this field.  Otherwise it remains NULL_TREE.  */
    1144              :   tree known_current_type;
    1145              :   HOST_WIDE_INT known_current_offset;
    1146              : 
    1147              :   /* Set to nonzero if we possibly missed some dynamic type changes and we
    1148              :      should consider the set to be speculative.  */
    1149              :   unsigned speculative;
    1150              : 
    1151              :   /* Set to true if dynamic type change has been detected.  */
    1152              :   bool type_maybe_changed;
    1153              :   /* Set to true if multiple types have been encountered.  known_current_type
    1154              :      must be disregarded in that case.  */
    1155              :   bool multiple_types_encountered;
    1156              :   bool seen_unanalyzed_store;
    1157              : };
    1158              : 
    1159              : /* Return true if STMT is not call and can modify a virtual method table pointer.
    1160              :    We take advantage of fact that vtable stores must appear within constructor
    1161              :    and destructor functions.  */
    1162              : 
    1163              : static bool
    1164      7370941 : noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
    1165              : {
    1166      7370941 :   if (is_gimple_assign (stmt))
    1167              :     {
    1168      7223200 :       tree lhs = gimple_assign_lhs (stmt);
    1169              : 
    1170      7223200 :       if (gimple_clobber_p (stmt))
    1171              :         return false;
    1172      6176332 :       if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
    1173              :         {
    1174      5475398 :           if (flag_strict_aliasing
    1175      5475398 :               && !POINTER_TYPE_P (TREE_TYPE (lhs)))
    1176              :             return false;
    1177              : 
    1178      2510135 :           if (TREE_CODE (lhs) == COMPONENT_REF
    1179      2510135 :               && !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
    1180              :             return false;
    1181              :           /* In the future we might want to use get_ref_base_and_extent to find
    1182              :              if there is a field corresponding to the offset and if so, proceed
    1183              :              almost like if it was a component ref.  */
    1184              :         }
    1185              :     }
    1186              : 
    1187              :   /* Code unification may mess with inline stacks.  */
    1188      1472085 :   if (cfun->after_inlining)
    1189              :     return true;
    1190              : 
    1191              :   /* Walk the inline stack and watch out for ctors/dtors.
    1192              :      TODO: Maybe we can require the store to appear in toplevel
    1193              :      block of CTOR/DTOR.  */
    1194     11431363 :   for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK;
    1195      4998973 :        block = BLOCK_SUPERCONTEXT (block))
    1196      5056940 :     if (BLOCK_ABSTRACT_ORIGIN (block)
    1197      5056940 :         && TREE_CODE (block_ultimate_origin (block)) == FUNCTION_DECL)
    1198        57967 :       return inlined_polymorphic_ctor_dtor_block_p (block, false);
    1199      1375450 :   return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
    1200      1375450 :           && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
    1201        70057 :               || DECL_CXX_DESTRUCTOR_P (current_function_decl)));
    1202              : }
    1203              : 
    1204              : /* If STMT can be proved to be an assignment to the virtual method table
    1205              :    pointer of ANALYZED_OBJ and the type associated with the new table
    1206              :    identified, return the type.  Otherwise return NULL_TREE if type changes
    1207              :    in unknown way or ERROR_MARK_NODE if type is unchanged.  */
    1208              : 
    1209              : static tree
    1210        74818 : extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
    1211              :                                HOST_WIDE_INT *type_offset)
    1212              : {
    1213        74818 :   poly_int64 offset, size, max_size;
    1214        74818 :   tree lhs, rhs, base;
    1215        74818 :   bool reverse;
    1216              : 
    1217        74818 :   if (!gimple_assign_single_p (stmt))
    1218              :     return NULL_TREE;
    1219              : 
    1220        74702 :   lhs = gimple_assign_lhs (stmt);
    1221        74702 :   rhs = gimple_assign_rhs1 (stmt);
    1222        74702 :   if (TREE_CODE (lhs) != COMPONENT_REF
    1223        74702 :       || !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
    1224              :      {
    1225        29854 :         if (dump_file)
    1226            0 :           fprintf (dump_file, "  LHS is not virtual table.\n");
    1227        29854 :         return NULL_TREE;
    1228              :      }
    1229              : 
    1230        44848 :   if (tci->vtbl_ptr_ref && operand_equal_p (lhs, tci->vtbl_ptr_ref, 0))
    1231              :     ;
    1232              :   else
    1233              :     {
    1234        44766 :       base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
    1235        44766 :       if (DECL_P (tci->instance))
    1236              :         {
    1237         1972 :           if (base != tci->instance)
    1238              :             {
    1239           16 :               if (dump_file)
    1240              :                 {
    1241            0 :                   fprintf (dump_file, "    base:");
    1242            0 :                   print_generic_expr (dump_file, base, TDF_SLIM);
    1243            0 :                   fprintf (dump_file, " does not match instance:");
    1244            0 :                   print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1245            0 :                   fprintf (dump_file, "\n");
    1246              :                 }
    1247           16 :               return NULL_TREE;
    1248              :             }
    1249              :         }
    1250        42794 :       else if (TREE_CODE (base) == MEM_REF)
    1251              :         {
    1252        35733 :           if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
    1253              :             {
    1254        23559 :               if (dump_file)
    1255              :                 {
    1256            0 :                   fprintf (dump_file, "    base mem ref:");
    1257            0 :                   print_generic_expr (dump_file, base, TDF_SLIM);
    1258            0 :                   fprintf (dump_file, " does not match instance:");
    1259            0 :                   print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1260            0 :                   fprintf (dump_file, "\n");
    1261              :                 }
    1262        23559 :               return NULL_TREE;
    1263              :             }
    1264        12174 :           if (!integer_zerop (TREE_OPERAND (base, 1)))
    1265              :             {
    1266         1443 :               if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
    1267              :                 {
    1268            0 :                   if (dump_file)
    1269              :                     {
    1270            0 :                       fprintf (dump_file, "    base mem ref:");
    1271            0 :                       print_generic_expr (dump_file, base, TDF_SLIM);
    1272            0 :                       fprintf (dump_file, " has non-representable offset:");
    1273            0 :                       print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1274            0 :                       fprintf (dump_file, "\n");
    1275              :                     }
    1276            0 :                   return NULL_TREE;
    1277              :                 }
    1278              :               else
    1279         1443 :                 offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
    1280              :             }
    1281              :         }
    1282         7061 :       else if (!operand_equal_p (tci->instance, base, 0)
    1283         7061 :                || tci->offset)
    1284              :         {
    1285         7061 :           if (dump_file)
    1286              :             {
    1287            0 :               fprintf (dump_file, "    base:");
    1288            0 :               print_generic_expr (dump_file, base, TDF_SLIM);
    1289            0 :               fprintf (dump_file, " does not match instance:");
    1290            0 :               print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1291            0 :               fprintf (dump_file, " with offset %i\n", (int)tci->offset);
    1292              :             }
    1293         7137 :           return tci->offset > POINTER_SIZE ? error_mark_node : NULL_TREE;
    1294              :         }
    1295        14130 :       if (maybe_ne (offset, tci->offset)
    1296        14535 :           || maybe_ne (size, POINTER_SIZE)
    1297        28665 :           || maybe_ne (max_size, POINTER_SIZE))
    1298              :         {
    1299           35 :           if (dump_file)
    1300              :             {
    1301            0 :               fprintf (dump_file, "    wrong offset ");
    1302            0 :               print_dec (offset, dump_file);
    1303            0 :               fprintf (dump_file, "!=%i or size ", (int) tci->offset);
    1304            0 :               print_dec (size, dump_file);
    1305            0 :               fprintf (dump_file, "\n");
    1306              :             }
    1307           35 :           return (known_le (offset + POINTER_SIZE, tci->offset)
    1308            0 :                   || (known_size_p (max_size)
    1309            0 :                       && known_gt (tci->offset + POINTER_SIZE,
    1310              :                                    offset + max_size))
    1311           35 :                   ? error_mark_node : NULL);
    1312              :         }
    1313              :     }
    1314              : 
    1315        14177 :   tree vtable;
    1316        14177 :   unsigned HOST_WIDE_INT offset2;
    1317              : 
    1318        14177 :   if (!vtable_pointer_value_to_vtable (rhs, &vtable, &offset2))
    1319              :     {
    1320           68 :       if (dump_file)
    1321            4 :         fprintf (dump_file, "    Failed to lookup binfo\n");
    1322           68 :       return NULL;
    1323              :     }
    1324              : 
    1325        14109 :   tree binfo = subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
    1326              :                                                offset2, vtable);
    1327        14109 :   if (!binfo)
    1328              :     {
    1329          175 :       if (dump_file)
    1330           13 :         fprintf (dump_file, "    Construction vtable used\n");
    1331              :       /* FIXME: We should support construction contexts.  */
    1332          175 :       return NULL;
    1333              :     }
    1334              : 
    1335        13934 :   *type_offset = tree_to_shwi (BINFO_OFFSET (binfo)) * BITS_PER_UNIT;
    1336        13934 :   return DECL_CONTEXT (vtable);
    1337              : }
    1338              : 
    1339              : /* Record dynamic type change of TCI to TYPE.  */
    1340              : 
    1341              : static void
    1342       143071 : record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
    1343              : {
    1344       143071 :   if (dump_file)
    1345              :     {
    1346           39 :       if (type)
    1347              :         {
    1348           39 :           fprintf (dump_file, "  Recording type: ");
    1349           39 :           print_generic_expr (dump_file, type, TDF_SLIM);
    1350           39 :           fprintf (dump_file, " at offset %i\n", (int)offset);
    1351              :         }
    1352              :      else
    1353            0 :        fprintf (dump_file, "  Recording unknown type\n");
    1354              :     }
    1355              : 
    1356              :   /* If we found a constructor of type that is not polymorphic or
    1357              :      that may contain the type in question as a field (not as base),
    1358              :      restrict to the inner class first to make type matching below
    1359              :      happier.  */
    1360       143071 :   if (type
    1361       143071 :       && (offset
    1362       137481 :           || (TREE_CODE (type) != RECORD_TYPE
    1363       137481 :               || !TYPE_BINFO (type)
    1364       137026 :               || !polymorphic_type_binfo_p (TYPE_BINFO (type)))))
    1365              :     {
    1366       126003 :       ipa_polymorphic_call_context context;
    1367              : 
    1368       126003 :       context.offset = offset;
    1369       126003 :       context.outer_type = type;
    1370       126003 :       context.maybe_in_construction = false;
    1371       126003 :       context.maybe_derived_type = false;
    1372       126003 :       context.dynamic = true;
    1373              :       /* If we failed to find the inner type, we know that the call
    1374              :          would be undefined for type produced here.  */
    1375       126003 :       if (!context.restrict_to_inner_class (tci->otr_type))
    1376              :         {
    1377          867 :           if (dump_file)
    1378            0 :             fprintf (dump_file, "  Ignoring; does not contain otr_type\n");
    1379          867 :           return;
    1380              :         }
    1381              :       /* Watch for case we reached an POD type and anticipate placement
    1382              :          new.  */
    1383       125136 :       if (!context.maybe_derived_type)
    1384              :         {
    1385          623 :           type = context.outer_type;
    1386          623 :           offset = context.offset;
    1387              :         }
    1388              :     }
    1389       142204 :   if (tci->type_maybe_changed
    1390       142204 :       && (!types_same_for_odr (type, tci->known_current_type)
    1391           21 :           || offset != tci->known_current_offset))
    1392            2 :     tci->multiple_types_encountered = true;
    1393       142204 :   tci->known_current_type = TYPE_MAIN_VARIANT (type);
    1394       142204 :   tci->known_current_offset = offset;
    1395       142204 :   tci->type_maybe_changed = true;
    1396              : }
    1397              : 
    1398              : 
    1399              : /* The maximum number of may-defs we visit when looking for a must-def
    1400              :    that changes the dynamic type in check_stmt_for_type_change.  Tuned
    1401              :    after the PR12392 testcase which unlimited spends 40% time within
    1402              :    these alias walks and 8% with the following limit.  */
    1403              : 
    1404              : static inline bool
    1405     16054156 : csftc_abort_walking_p (unsigned speculative)
    1406              : {
    1407     16054156 :   unsigned max = param_max_speculative_devirt_maydefs;
    1408     16054156 :   return speculative > max ? true : false;
    1409              : }
    1410              : 
    1411              : /* Callback of walk_aliased_vdefs and a helper function for
    1412              :    detect_type_change to check whether a particular statement may modify
    1413              :    the virtual table pointer, and if possible also determine the new type of
    1414              :    the (sub-)object.  It stores its result into DATA, which points to a
    1415              :    type_change_info structure.  */
    1416              : 
    1417              : static bool
    1418     23616316 : check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
    1419              : {
    1420     23616316 :   gimple *stmt = SSA_NAME_DEF_STMT (vdef);
    1421     23616316 :   struct type_change_info *tci = (struct type_change_info *) data;
    1422     23616316 :   tree fn;
    1423              : 
    1424              :   /* If we already gave up, just terminate the rest of walk.  */
    1425     23616316 :   if (tci->multiple_types_encountered)
    1426              :     return true;
    1427              : 
    1428     23616316 :   if (is_gimple_call (stmt))
    1429              :     {
    1430     16245375 :       if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
    1431              :         return false;
    1432              : 
    1433              :       /* Check for a constructor call.  */
    1434     16183293 :       if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
    1435     14714768 :           && DECL_CXX_CONSTRUCTOR_P (fn)
    1436      1026325 :           && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
    1437     17209618 :           && gimple_call_num_args (stmt))
    1438              :       {
    1439      1026325 :         tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
    1440      1026325 :         tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
    1441      1026325 :         HOST_WIDE_INT offset = 0;
    1442      1026325 :         bool reverse;
    1443              : 
    1444      1026325 :         if (dump_file)
    1445              :           {
    1446           31 :             fprintf (dump_file, "  Checking constructor call: ");
    1447           31 :             print_gimple_stmt (dump_file, stmt, 0);
    1448              :           }
    1449              : 
    1450              :         /* See if THIS parameter seems like instance pointer.  */
    1451      1026325 :         if (TREE_CODE (op) == ADDR_EXPR)
    1452              :           {
    1453       988894 :             HOST_WIDE_INT size;
    1454       988894 :             op = get_ref_base_and_extent_hwi (TREE_OPERAND (op, 0),
    1455              :                                               &offset, &size, &reverse);
    1456       988894 :             if (!op)
    1457              :               {
    1458            0 :                 tci->speculative++;
    1459            0 :                 return csftc_abort_walking_p (tci->speculative);
    1460              :               }
    1461       988894 :             if (TREE_CODE (op) == MEM_REF)
    1462              :               {
    1463        99508 :                 if (!tree_fits_shwi_p (TREE_OPERAND (op, 1)))
    1464              :                   {
    1465            0 :                     tci->speculative++;
    1466            0 :                     return csftc_abort_walking_p (tci->speculative);
    1467              :                   }
    1468        99508 :                 offset += tree_to_shwi (TREE_OPERAND (op, 1))
    1469        99508 :                           * BITS_PER_UNIT;
    1470        99508 :                 op = TREE_OPERAND (op, 0);
    1471              :               }
    1472       889386 :             else if (DECL_P (op))
    1473              :               ;
    1474              :             else
    1475              :               {
    1476            0 :                 tci->speculative++;
    1477            0 :                 return csftc_abort_walking_p (tci->speculative);
    1478              :               }
    1479       988894 :             op = walk_ssa_copies (op);
    1480              :           }
    1481      1026325 :         if (operand_equal_p (op, tci->instance, 0)
    1482       182256 :             && TYPE_SIZE (type)
    1483       182256 :             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
    1484       182256 :             && tree_fits_shwi_p (TYPE_SIZE (type))
    1485       182256 :             && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset
    1486              :             /* Some inlined constructors may look as follows:
    1487              :                   _3 = operator new (16);
    1488              :                   MEM[(struct  &)_3] ={v} {CLOBBER};
    1489              :                   MEM[(struct CompositeClass *)_3]._vptr.CompositeClass
    1490              :                     = &MEM[(void *)&_ZTV14CompositeClass + 16B];
    1491              :                   _7 = &MEM[(struct CompositeClass *)_3].object;
    1492              :                   EmptyClass::EmptyClass (_7);
    1493              : 
    1494              :                When determining dynamic type of _3 and because we stop at first
    1495              :                dynamic type found, we would stop on EmptyClass::EmptyClass (_7).
    1496              :                In this case the emptyclass is not even polymorphic and we miss
    1497              :                it is contained in an outer type that is polymorphic.  */
    1498              : 
    1499      1176333 :             && (tci->offset == offset || contains_polymorphic_type_p (type)))
    1500              :           {
    1501       129137 :             record_known_type (tci, type, tci->offset - offset);
    1502       129137 :             return true;
    1503              :           }
    1504              :       }
    1505              :      /* Calls may possibly change dynamic type by placement new. Assume
    1506              :         it will not happen, but make result speculative only.  */
    1507     16054156 :      if (dump_file)
    1508              :         {
    1509          736 :           fprintf (dump_file, "  Function call may change dynamic type:");
    1510          736 :           print_gimple_stmt (dump_file, stmt, 0);
    1511              :         }
    1512     16054156 :      tci->speculative++;
    1513     16054156 :      return csftc_abort_walking_p (tci->speculative);
    1514              :    }
    1515              :   /* Check for inlined virtual table store.  */
    1516      7370941 :   else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
    1517              :     {
    1518        74818 :       tree type;
    1519        74818 :       HOST_WIDE_INT offset = 0;
    1520        74818 :       if (dump_file)
    1521              :         {
    1522           38 :           fprintf (dump_file, "  Checking vtbl store: ");
    1523           38 :           print_gimple_stmt (dump_file, stmt, 0);
    1524              :         }
    1525              : 
    1526        74818 :       type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
    1527        74818 :       if (type == error_mark_node)
    1528              :         return false;
    1529        74778 :       gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
    1530        74778 :       if (!type)
    1531              :         {
    1532        60844 :           if (dump_file)
    1533           17 :             fprintf (dump_file, "  Unanalyzed store may change type.\n");
    1534        60844 :           tci->seen_unanalyzed_store = true;
    1535        60844 :           tci->speculative++;
    1536              :         }
    1537              :       else
    1538        13934 :         record_known_type (tci, type, offset);
    1539        74778 :       return true;
    1540              :     }
    1541              :   else
    1542              :     return false;
    1543              : }
    1544              : 
    1545              : /* THIS is polymorphic call context obtained from get_polymorphic_context.
    1546              :    OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
    1547              :    INSTANCE is pointer to the outer instance as returned by
    1548              :    get_polymorphic_context.  To avoid creation of temporary expressions,
    1549              :    INSTANCE may also be an declaration of get_polymorphic_context found the
    1550              :    value to be in static storage.
    1551              : 
    1552              :    If the type of instance is not fully determined
    1553              :    (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
    1554              :    is set), try to walk memory writes and find the actual construction of the
    1555              :    instance.
    1556              : 
    1557              :    Return true if memory is unchanged from function entry.
    1558              : 
    1559              :    We do not include this analysis in the context analysis itself, because
    1560              :    it needs memory SSA to be fully built and the walk may be expensive.
    1561              :    So it is not suitable for use withing fold_stmt and similar uses.
    1562              : 
    1563              :    AA_WALK_BUDGET_P, if not NULL, is how statements we should allow
    1564              :    walk_aliased_vdefs to examine.  The value should be decremented by the
    1565              :    number of statements we examined or set to zero if exhausted.  */
    1566              : 
    1567              : bool
    1568      3421626 : ipa_polymorphic_call_context::get_dynamic_type (tree instance,
    1569              :                                                 tree otr_object,
    1570              :                                                 tree otr_type,
    1571              :                                                 gimple *call,
    1572              :                                                 unsigned *aa_walk_budget_p)
    1573              : {
    1574      3421626 :   struct type_change_info tci;
    1575      3421626 :   ao_ref ao;
    1576      3421626 :   bool function_entry_reached = false;
    1577      3421626 :   tree instance_ref = NULL;
    1578      3421626 :   gimple *stmt = call;
    1579              :   /* Remember OFFSET before it is modified by restrict_to_inner_class.
    1580              :      This is because we do not update INSTANCE when walking inwards.  */
    1581      3421626 :   HOST_WIDE_INT instance_offset = offset;
    1582      3421626 :   tree instance_outer_type = outer_type;
    1583              : 
    1584      3421626 :   if (!instance)
    1585              :     return false;
    1586              : 
    1587      3421621 :   if (otr_type)
    1588       205408 :     otr_type = TYPE_MAIN_VARIANT (otr_type);
    1589              : 
    1590              :   /* Walk into inner type. This may clear maybe_derived_type and save us
    1591              :      from useless work.  It also makes later comparisons with static type
    1592              :      easier.  */
    1593      3421621 :   if (outer_type && otr_type)
    1594              :     {
    1595       182473 :       if (!restrict_to_inner_class (otr_type))
    1596              :         return false;
    1597              :     }
    1598              : 
    1599      3421621 :   if (!maybe_in_construction && !maybe_derived_type)
    1600              :     return false;
    1601              : 
    1602              :   /* If we are in fact not looking at any object or the instance is
    1603              :      some placement new into a random load, give up straight away.  */
    1604      3391354 :   if (TREE_CODE (instance) == MEM_REF)
    1605              :     return false;
    1606              : 
    1607              :   /* We need to obtain reference to virtual table pointer.  It is better
    1608              :      to look it up in the code rather than build our own.  This require bit
    1609              :      of pattern matching, but we end up verifying that what we found is
    1610              :      correct.
    1611              : 
    1612              :      What we pattern match is:
    1613              : 
    1614              :        tmp = instance->_vptr.A;   // vtbl ptr load
    1615              :        tmp2 = tmp[otr_token];     // vtable lookup
    1616              :        OBJ_TYPE_REF(tmp2;instance->0) (instance);
    1617              : 
    1618              :      We want to start alias oracle walk from vtbl pointer load,
    1619              :      but we may not be able to identify it, for example, when PRE moved the
    1620              :      load around.  */
    1621              : 
    1622      3391354 :   if (gimple_code (call) == GIMPLE_CALL)
    1623              :     {
    1624      3391354 :       tree ref = gimple_call_fn (call);
    1625      3391354 :       bool reverse;
    1626              : 
    1627      3391354 :       if (TREE_CODE (ref) == OBJ_TYPE_REF)
    1628              :         {
    1629       240511 :           ref = OBJ_TYPE_REF_EXPR (ref);
    1630       240511 :           ref = walk_ssa_copies (ref);
    1631              : 
    1632              :           /* If call target is already known, no need to do the expensive
    1633              :              memory walk.  */
    1634       240511 :           if (is_gimple_min_invariant (ref))
    1635            0 :             return false;
    1636              : 
    1637              :           /* Check if definition looks like vtable lookup.  */
    1638       240511 :           if (TREE_CODE (ref) == SSA_NAME
    1639       240511 :               && !SSA_NAME_IS_DEFAULT_DEF (ref)
    1640       240511 :               && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))
    1641       480920 :               && TREE_CODE (gimple_assign_rhs1
    1642              :                              (SSA_NAME_DEF_STMT (ref))) == MEM_REF)
    1643              :             {
    1644       240389 :               ref = get_base_address
    1645       240389 :                      (TREE_OPERAND (gimple_assign_rhs1
    1646              :                                      (SSA_NAME_DEF_STMT (ref)), 0));
    1647       240389 :               ref = walk_ssa_copies (ref);
    1648              :               /* Find base address of the lookup and see if it looks like
    1649              :                  vptr load.  */
    1650       240389 :               if (TREE_CODE (ref) == SSA_NAME
    1651       240249 :                   && !SSA_NAME_IS_DEFAULT_DEF (ref)
    1652       480638 :                   && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
    1653              :                 {
    1654       238213 :                   HOST_WIDE_INT offset2, size;
    1655       238213 :                   tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
    1656       238213 :                   tree base_ref
    1657       238213 :                     = get_ref_base_and_extent_hwi (ref_exp, &offset2,
    1658              :                                                    &size, &reverse);
    1659              : 
    1660              :                   /* Finally verify that what we found looks like read from
    1661              :                      OTR_OBJECT or from INSTANCE with offset OFFSET.  */
    1662       238213 :                   if (base_ref
    1663       238213 :                       && ((TREE_CODE (base_ref) == MEM_REF
    1664       234800 :                            && ((offset2 == instance_offset
    1665       231735 :                                 && TREE_OPERAND (base_ref, 0) == instance)
    1666        16586 :                                || (!offset2
    1667        16586 :                                    && TREE_OPERAND (base_ref, 0)
    1668              :                                       == otr_object)))
    1669        18277 :                           || (DECL_P (instance) && base_ref == instance
    1670         3256 :                               && offset2 == instance_offset)))
    1671              :                     {
    1672       223192 :                       stmt = SSA_NAME_DEF_STMT (ref);
    1673       223192 :                       instance_ref = ref_exp;
    1674              :                     }
    1675              :                 }
    1676              :             }
    1677              :         }
    1678              :     }
    1679              : 
    1680              :   /* If we failed to look up the reference in code, build our own.  */
    1681      3391354 :   if (!instance_ref)
    1682              :     {
    1683              :       /* If the statement in question does not use memory, we can't tell
    1684              :          anything.  */
    1685      9545397 :       if (!gimple_vuse (stmt))
    1686              :         return false;
    1687      3159308 :       ao_ref_init_from_ptr_and_size (&ao, otr_object, NULL);
    1688              :     }
    1689              :   else
    1690              :   /* Otherwise use the real reference.  */
    1691       223192 :     ao_ref_init (&ao, instance_ref);
    1692              : 
    1693              :   /* We look for vtbl pointer read.  */
    1694      3619958 :   ao.size = POINTER_SIZE;
    1695      3382500 :   ao.max_size = ao.size;
    1696              :   /* We are looking for stores to vptr pointer within the instance of
    1697              :      outer type.
    1698              :      TODO: The vptr pointer type is globally known, we probably should
    1699              :      keep it and do that even when otr_type is unknown.  */
    1700      3382500 :   if (otr_type)
    1701              :     {
    1702       204744 :       ao.base_alias_set
    1703       386553 :         = get_alias_set (outer_type ? outer_type : otr_type);
    1704       204744 :       ao.ref_alias_set
    1705       204744 :         = get_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type))));
    1706              :     }
    1707              : 
    1708      3382500 :   if (dump_file)
    1709              :     {
    1710          621 :       fprintf (dump_file, "Determining dynamic type for call: ");
    1711          621 :       print_gimple_stmt (dump_file, call, 0);
    1712          621 :       fprintf (dump_file, "  Starting walk at: ");
    1713          621 :       print_gimple_stmt (dump_file, stmt, 0);
    1714          621 :       fprintf (dump_file, "  instance pointer: ");
    1715          621 :       print_generic_expr (dump_file, otr_object, TDF_SLIM);
    1716          621 :       fprintf (dump_file, "  Outer instance pointer: ");
    1717          621 :       print_generic_expr (dump_file, instance, TDF_SLIM);
    1718          621 :       fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
    1719          621 :       fprintf (dump_file, " vtbl reference: ");
    1720          621 :       print_generic_expr (dump_file, instance_ref, TDF_SLIM);
    1721          621 :       fprintf (dump_file, "\n");
    1722              :     }
    1723              : 
    1724      3382500 :   tci.offset = instance_offset;
    1725      3382500 :   tci.instance = instance;
    1726      3382500 :   tci.vtbl_ptr_ref = instance_ref;
    1727      3382500 :   tci.known_current_type = NULL_TREE;
    1728      3382500 :   tci.known_current_offset = 0;
    1729      3382500 :   tci.otr_type = otr_type;
    1730      3382500 :   tci.type_maybe_changed = false;
    1731      3382500 :   tci.multiple_types_encountered = false;
    1732      3382500 :   tci.speculative = 0;
    1733      3382500 :   tci.seen_unanalyzed_store = false;
    1734              : 
    1735      3382500 :   unsigned aa_walk_budget = 0;
    1736      3382500 :   if (aa_walk_budget_p)
    1737      3201463 :     aa_walk_budget = *aa_walk_budget_p + 1;
    1738              : 
    1739      3382500 :   int walked
    1740      3382500 :    = walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
    1741              :                          &tci, NULL, &function_entry_reached, aa_walk_budget);
    1742              : 
    1743              :   /* If we did not find any type changing statements, we may still drop
    1744              :      maybe_in_construction flag if the context already have outer type.
    1745              : 
    1746              :      Here we make special assumptions about both constructors and
    1747              :      destructors which are all the functions that are allowed to alter the
    1748              :      VMT pointers.  It assumes that destructors begin with assignment into
    1749              :      all VMT pointers and that constructors essentially look in the
    1750              :      following way:
    1751              : 
    1752              :      1) The very first thing they do is that they call constructors of
    1753              :      ancestor sub-objects that have them.
    1754              : 
    1755              :      2) Then VMT pointers of this and all its ancestors is set to new
    1756              :      values corresponding to the type corresponding to the constructor.
    1757              : 
    1758              :      3) Only afterwards, other stuff such as constructor of member
    1759              :      sub-objects and the code written by the user is run.  Only this may
    1760              :      include calling virtual functions, directly or indirectly.
    1761              : 
    1762              :      4) placement new cannot be used to change type of non-POD statically
    1763              :      allocated variables.
    1764              : 
    1765              :      There is no way to call a constructor of an ancestor sub-object in any
    1766              :      other way.
    1767              : 
    1768              :      This means that we do not have to care whether constructors get the
    1769              :      correct type information because they will always change it (in fact,
    1770              :      if we define the type to be given by the VMT pointer, it is undefined).
    1771              : 
    1772              :      The most important fact to derive from the above is that if, for some
    1773              :      statement in the section 3, we try to detect whether the dynamic type
    1774              :      has changed, we can safely ignore all calls as we examine the function
    1775              :      body backwards until we reach statements in section 2 because these
    1776              :      calls cannot be ancestor constructors or destructors (if the input is
    1777              :      not bogus) and so do not change the dynamic type (this holds true only
    1778              :      for automatically allocated objects but at the moment we devirtualize
    1779              :      only these).  We then must detect that statements in section 2 change
    1780              :      the dynamic type and can try to derive the new type.  That is enough
    1781              :      and we can stop, we will never see the calls into constructors of
    1782              :      sub-objects in this code.
    1783              : 
    1784              :      Therefore if the static outer type was found (outer_type)
    1785              :      we can safely ignore tci.speculative that is set on calls and give up
    1786              :      only if there was dynamic type store that may affect given variable
    1787              :      (seen_unanalyzed_store)  */
    1788              : 
    1789      3382500 :   if (walked < 0)
    1790              :     {
    1791       113121 :       if (dump_file)
    1792            0 :         fprintf (dump_file, "  AA walk budget exhausted.\n");
    1793       113121 :       *aa_walk_budget_p = 0;
    1794       113121 :       return false;
    1795              :     }
    1796      3269379 :   else if (aa_walk_budget_p)
    1797      3088342 :     *aa_walk_budget_p -= walked;
    1798              : 
    1799      3269379 :   if (!tci.type_maybe_changed
    1800      3269379 :       || (outer_type
    1801        21214 :           && !dynamic
    1802         3122 :           && !tci.seen_unanalyzed_store
    1803         3122 :           && !tci.multiple_types_encountered
    1804         3122 :           && ((offset == tci.offset
    1805         2849 :                && types_same_for_odr (tci.known_current_type,
    1806              :                                       outer_type))
    1807          487 :                || (instance_offset == offset
    1808          214 :                    && types_same_for_odr (tci.known_current_type,
    1809              :                                           instance_outer_type)))))
    1810              :     {
    1811      3129837 :       if (!outer_type || tci.seen_unanalyzed_store)
    1812              :         return false;
    1813       203699 :       if (maybe_in_construction)
    1814       138762 :         maybe_in_construction = false;
    1815       203699 :       if (dump_file)
    1816          225 :         fprintf (dump_file, "  No dynamic type change found.\n");
    1817       203699 :       return true;
    1818              :     }
    1819              : 
    1820       139542 :   if (tci.known_current_type
    1821       139542 :       && !function_entry_reached
    1822       135915 :       && !tci.multiple_types_encountered)
    1823              :     {
    1824       135914 :       if (!tci.speculative)
    1825              :         {
    1826        44108 :           outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
    1827        44108 :           offset = tci.known_current_offset;
    1828        44108 :           dynamic = true;
    1829        44108 :           maybe_in_construction = false;
    1830        44108 :           maybe_derived_type = false;
    1831        44108 :           if (dump_file)
    1832           28 :             fprintf (dump_file, "  Determined dynamic type.\n");
    1833              :         }
    1834        91806 :       else if (!speculative_outer_type
    1835         5044 :                || speculative_maybe_derived_type)
    1836              :         {
    1837        91806 :           speculative_outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
    1838        91806 :           speculative_offset = tci.known_current_offset;
    1839        91806 :           speculative_maybe_derived_type = false;
    1840        91806 :           if (dump_file)
    1841            8 :             fprintf (dump_file, "  Determined speculative dynamic type.\n");
    1842              :         }
    1843              :     }
    1844         3628 :   else if (dump_file)
    1845              :     {
    1846            0 :       fprintf (dump_file, "  Found multiple types%s%s\n",
    1847              :                function_entry_reached ? " (function entry reached)" : "",
    1848              :                function_entry_reached ? " (multiple types encountered)" : "");
    1849              :     }
    1850              : 
    1851              :   return false;
    1852              : }
    1853              : 
    1854              : /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
    1855              :    seems consistent (and useful) with what we already have in the non-speculative context.  */
    1856              : 
    1857              : bool
    1858      4707948 : ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type,
    1859              :                                                         HOST_WIDE_INT spec_offset,
    1860              :                                                         bool spec_maybe_derived_type,
    1861              :                                                         tree otr_type) const
    1862              : {
    1863      4707948 :   if (!flag_devirtualize_speculatively)
    1864              :     return false;
    1865              : 
    1866              :   /* Non-polymorphic types are useless for deriving likely polymorphic
    1867              :      call targets.  */
    1868      4699654 :   if (!spec_outer_type || !contains_polymorphic_type_p (spec_outer_type))
    1869      3440306 :     return false;
    1870              : 
    1871              :   /* If we know nothing, speculation is always good.  */
    1872      1259348 :   if (!outer_type)
    1873              :     return true;
    1874              : 
    1875              :   /* Speculation is only useful to avoid derived types.
    1876              :      This is not 100% true for placement new, where the outer context may
    1877              :      turn out to be useless, but ignore these for now.  */
    1878       859200 :   if (!maybe_derived_type)
    1879              :     return false;
    1880              : 
    1881              :   /* If types agrees, speculation is consistent, but it makes sense only
    1882              :      when it says something new.  */
    1883       838168 :   if (types_must_be_same_for_odr (spec_outer_type, outer_type))
    1884      1245283 :     return maybe_derived_type && !spec_maybe_derived_type;
    1885              : 
    1886              :   /* If speculation does not contain the type in question, ignore it.  */
    1887       215445 :   if (otr_type
    1888       215445 :       && !contains_type_p (spec_outer_type, spec_offset, otr_type, false, true))
    1889              :     return false;
    1890              : 
    1891              :   /* If outer type already contains speculation as a filed,
    1892              :      it is useless.  We already know from OUTER_TYPE
    1893              :      SPEC_TYPE and that it is not in the construction.  */
    1894       213075 :   if (contains_type_p (outer_type, offset - spec_offset,
    1895              :                        spec_outer_type, false, false))
    1896              :     return false;
    1897              : 
    1898              :   /* If speculative outer type is not more specified than outer
    1899              :      type, just give up.
    1900              :      We can only decide this safely if we can compare types with OUTER_TYPE.
    1901              :    */
    1902           84 :   if ((!in_lto_p || odr_type_p (outer_type))
    1903       425860 :       && !contains_type_p (spec_outer_type,
    1904       212930 :                            spec_offset - offset,
    1905       212930 :                            outer_type, false))
    1906              :     return false;
    1907              :   return true;
    1908              : }
    1909              : 
    1910              : /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
    1911              :    NEW_MAYBE_DERIVED_TYPE
    1912              :    If OTR_TYPE is set, assume the context is used with OTR_TYPE.  */
    1913              : 
    1914              : bool
    1915      4522137 : ipa_polymorphic_call_context::combine_speculation_with
    1916              :    (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
    1917              :     tree otr_type)
    1918              : {
    1919      4522137 :   if (!new_outer_type)
    1920              :     return false;
    1921              : 
    1922              :   /* restrict_to_inner_class may eliminate wrong speculation making our job
    1923              :      easier.  */
    1924      4444186 :   if (otr_type)
    1925         3996 :     restrict_to_inner_class (otr_type);
    1926              : 
    1927      4444186 :   if (!speculation_consistent_p (new_outer_type, new_offset,
    1928              :                                  new_maybe_derived_type, otr_type))
    1929              :     return false;
    1930              : 
    1931              :   /* New speculation is a win in case we have no speculation or new
    1932              :      speculation does not consider derivations.  */
    1933       331158 :   if (!speculative_outer_type
    1934        82978 :       || (speculative_maybe_derived_type
    1935        82779 :           && !new_maybe_derived_type))
    1936              :     {
    1937       248348 :       speculative_outer_type = new_outer_type;
    1938       248348 :       speculative_offset = new_offset;
    1939       248348 :       speculative_maybe_derived_type = new_maybe_derived_type;
    1940       248348 :       return true;
    1941              :     }
    1942        82810 :   else if (types_must_be_same_for_odr (speculative_outer_type,
    1943              :                                        new_outer_type))
    1944              :     {
    1945        62336 :       if (speculative_offset != new_offset)
    1946              :         {
    1947              :           /* OK we have two contexts that seems valid but they disagree,
    1948              :              just give up.
    1949              : 
    1950              :              This is not a lattice operation, so we may want to drop it later.  */
    1951            4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1952            0 :             fprintf (dump_file,
    1953              :                      "Speculative outer types match, "
    1954              :                      "offset mismatch -> invalid speculation\n");
    1955            4 :           clear_speculation ();
    1956            4 :           return true;
    1957              :         }
    1958              :       else
    1959              :         {
    1960        62332 :           if (speculative_maybe_derived_type && !new_maybe_derived_type)
    1961              :             {
    1962            0 :               speculative_maybe_derived_type = false;
    1963            0 :               return true;
    1964              :             }
    1965              :           else
    1966              :             return false;
    1967              :         }
    1968              :     }
    1969              :   /* Choose type that contains the other.  This one either contains the outer
    1970              :      as a field (thus giving exactly one target) or is deeper in the type
    1971              :      hierarchy.  */
    1972        20474 :   else if (speculative_outer_type
    1973        20474 :            && speculative_maybe_derived_type
    1974        40781 :            && (new_offset > speculative_offset
    1975        19746 :                || (new_offset == speculative_offset
    1976        19698 :                    && contains_type_p (new_outer_type,
    1977              :                                        0, speculative_outer_type, false))))
    1978              :     {
    1979          962 :       tree old_outer_type = speculative_outer_type;
    1980          962 :       HOST_WIDE_INT old_offset = speculative_offset;
    1981          962 :       bool old_maybe_derived_type = speculative_maybe_derived_type;
    1982              : 
    1983          962 :       speculative_outer_type = new_outer_type;
    1984          962 :       speculative_offset = new_offset;
    1985          962 :       speculative_maybe_derived_type = new_maybe_derived_type;
    1986              : 
    1987          962 :       if (otr_type)
    1988            0 :         restrict_to_inner_class (otr_type);
    1989              : 
    1990              :       /* If the speculation turned out to make no sense, revert to sensible
    1991              :          one.  */
    1992          962 :       if (!speculative_outer_type)
    1993              :         {
    1994            0 :           speculative_outer_type = old_outer_type;
    1995            0 :           speculative_offset = old_offset;
    1996            0 :           speculative_maybe_derived_type = old_maybe_derived_type;
    1997            0 :           return false;
    1998              :         }
    1999          962 :       return (old_offset != speculative_offset
    2000          401 :               || old_maybe_derived_type != speculative_maybe_derived_type
    2001         1363 :               || types_must_be_same_for_odr (speculative_outer_type,
    2002              :                                              new_outer_type));
    2003              :     }
    2004              :   return false;
    2005              : }
    2006              : 
    2007              : /* Make speculation less specific so
    2008              :    NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
    2009              :    If OTR_TYPE is set, assume the context is used with OTR_TYPE.  */
    2010              : 
    2011              : bool
    2012           59 : ipa_polymorphic_call_context::meet_speculation_with
    2013              :    (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
    2014              :     tree otr_type)
    2015              : {
    2016           59 :   if (!new_outer_type && speculative_outer_type)
    2017              :     {
    2018            2 :       clear_speculation ();
    2019            2 :       return true;
    2020              :     }
    2021              : 
    2022              :   /* restrict_to_inner_class may eliminate wrong speculation making our job
    2023              :      easier.  */
    2024           57 :   if (otr_type)
    2025            0 :     restrict_to_inner_class (otr_type);
    2026              : 
    2027           57 :   if (!speculative_outer_type
    2028           84 :       || !speculation_consistent_p (speculative_outer_type,
    2029              :                                     speculative_offset,
    2030           27 :                                     speculative_maybe_derived_type,
    2031              :                                     otr_type))
    2032           31 :     return false;
    2033              : 
    2034           26 :   if (!speculation_consistent_p (new_outer_type, new_offset,
    2035              :                                  new_maybe_derived_type, otr_type))
    2036              :     {
    2037            0 :       clear_speculation ();
    2038            0 :       return true;
    2039              :     }
    2040              : 
    2041           26 :   else if (types_must_be_same_for_odr (speculative_outer_type,
    2042              :                                        new_outer_type))
    2043              :     {
    2044            4 :       if (speculative_offset != new_offset)
    2045              :         {
    2046            0 :           clear_speculation ();
    2047            0 :           return true;
    2048              :         }
    2049              :       else
    2050              :         {
    2051            4 :           if (!speculative_maybe_derived_type && new_maybe_derived_type)
    2052              :             {
    2053            0 :               speculative_maybe_derived_type = true;
    2054            0 :               return true;
    2055              :             }
    2056              :           else
    2057              :             return false;
    2058              :         }
    2059              :     }
    2060              :   /* See if one type contains the other as a field (not base).  */
    2061           22 :   else if (contains_type_p (new_outer_type, new_offset - speculative_offset,
    2062              :                             speculative_outer_type, false, false))
    2063              :     return false;
    2064           22 :   else if (contains_type_p (speculative_outer_type,
    2065           22 :                             speculative_offset - new_offset,
    2066              :                             new_outer_type, false, false))
    2067              :     {
    2068            0 :       speculative_outer_type = new_outer_type;
    2069            0 :       speculative_offset = new_offset;
    2070            0 :       speculative_maybe_derived_type = new_maybe_derived_type;
    2071            0 :       return true;
    2072              :     }
    2073              :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2074           22 :   else if (contains_type_p (new_outer_type,
    2075           22 :                             new_offset - speculative_offset,
    2076              :                             speculative_outer_type, false, true))
    2077              :     {
    2078           19 :       if (!speculative_maybe_derived_type)
    2079              :         {
    2080            0 :           speculative_maybe_derived_type = true;
    2081            0 :           return true;
    2082              :         }
    2083              :       return false;
    2084              :     }
    2085              :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2086            3 :   else if (contains_type_p (speculative_outer_type,
    2087            3 :                             speculative_offset - new_offset, new_outer_type, false, true))
    2088              :     {
    2089            0 :       speculative_outer_type = new_outer_type;
    2090            0 :       speculative_offset = new_offset;
    2091            0 :       speculative_maybe_derived_type = true;
    2092            0 :       return true;
    2093              :     }
    2094              :   else
    2095              :     {
    2096            3 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2097            0 :         fprintf (dump_file, "Giving up on speculative meet\n");
    2098            3 :       clear_speculation ();
    2099            3 :       return true;
    2100              :     }
    2101              : }
    2102              : 
    2103              : /* Assume that both THIS and a given context is valid and strengthen THIS
    2104              :    if possible.  Return true if any strengthening was made.
    2105              :    If actual type the context is being used in is known, OTR_TYPE should be
    2106              :    set accordingly. This improves quality of combined result.  */
    2107              : 
    2108              : bool
    2109       133649 : ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
    2110              :                                             tree otr_type)
    2111              : {
    2112       133649 :   bool updated = false;
    2113              : 
    2114       183557 :   if (ctx.useless_p () || invalid)
    2115              :     return false;
    2116              : 
    2117              :   /* Restricting context to inner type makes merging easier, however do not
    2118              :      do that unless we know how the context is used (OTR_TYPE is non-NULL)  */
    2119       132554 :   if (otr_type && !invalid && !ctx.invalid)
    2120              :     {
    2121        28946 :       restrict_to_inner_class (otr_type);
    2122        28946 :       ctx.restrict_to_inner_class (otr_type);
    2123        28946 :       if(invalid)
    2124              :         return false;
    2125              :     }
    2126              : 
    2127       132503 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2128              :     {
    2129          101 :       fprintf (dump_file, "Polymorphic call context combine:");
    2130          101 :       dump (dump_file);
    2131          101 :       fprintf (dump_file, "With context:                    ");
    2132          101 :       ctx.dump (dump_file);
    2133          101 :       if (otr_type)
    2134              :         {
    2135           59 :           fprintf (dump_file, "To be used with type:            ");
    2136           59 :           print_generic_expr (dump_file, otr_type, TDF_SLIM);
    2137           59 :           fprintf (dump_file, "\n");
    2138              :         }
    2139              :     }
    2140              : 
    2141              :   /* If call is known to be invalid, we are done.  */
    2142       132503 :   if (ctx.invalid)
    2143              :     {
    2144            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2145            0 :         fprintf (dump_file, "-> Invalid context\n");
    2146            0 :       goto invalidate;
    2147              :     }
    2148              : 
    2149       132503 :   if (!ctx.outer_type)
    2150              :     ;
    2151        83875 :   else if (!outer_type)
    2152              :     {
    2153        19072 :       outer_type = ctx.outer_type;
    2154        19072 :       offset = ctx.offset;
    2155        19072 :       dynamic = ctx.dynamic;
    2156        19072 :       maybe_in_construction = ctx.maybe_in_construction;
    2157        19072 :       maybe_derived_type = ctx.maybe_derived_type;
    2158        19072 :       updated = true;
    2159              :     }
    2160              :   /* If types are known to be same, merging is quite easy.  */
    2161        64803 :   else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
    2162              :     {
    2163        39831 :       if (offset != ctx.offset
    2164            4 :           && TYPE_SIZE (outer_type)
    2165        39835 :           && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
    2166              :         {
    2167            4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2168            0 :             fprintf (dump_file, "Outer types match, offset mismatch -> invalid\n");
    2169            4 :           clear_speculation ();
    2170            4 :           clear_outer_type ();
    2171            4 :           invalid = true;
    2172            4 :           return true;
    2173              :         }
    2174        39827 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2175           21 :         fprintf (dump_file, "Outer types match, merging flags\n");
    2176        39827 :       if (maybe_in_construction && !ctx.maybe_in_construction)
    2177              :         {
    2178        10437 :           updated = true;
    2179        10437 :           maybe_in_construction = false;
    2180              :         }
    2181        39827 :       if (maybe_derived_type && !ctx.maybe_derived_type)
    2182              :         {
    2183         2708 :           updated = true;
    2184         2708 :           maybe_derived_type = false;
    2185              :         }
    2186        39827 :       if (dynamic && !ctx.dynamic)
    2187              :         {
    2188        11844 :           updated = true;
    2189        11844 :           dynamic = false;
    2190              :         }
    2191              :     }
    2192              :   /* If we know the type precisely, there is not much to improve.  */
    2193        24972 :   else if (!maybe_derived_type && !maybe_in_construction
    2194        15395 :            && !ctx.maybe_derived_type && !ctx.maybe_in_construction)
    2195              :     {
    2196              :       /* It may be easy to check if second context permits the first
    2197              :          and set INVALID otherwise.  This is not easy to do in general;
    2198              :          contains_type_p may return false negatives for non-comparable
    2199              :          types.
    2200              : 
    2201              :          If OTR_TYPE is known, we however can expect that
    2202              :          restrict_to_inner_class should have discovered the same base
    2203              :          type.  */
    2204         1040 :       if (otr_type && !ctx.maybe_in_construction && !ctx.maybe_derived_type)
    2205              :         {
    2206            0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2207            0 :             fprintf (dump_file, "Contextes disagree -> invalid\n");
    2208            0 :           goto invalidate;
    2209              :         }
    2210              :     }
    2211              :   /* See if one type contains the other as a field (not base).
    2212              :      In this case we want to choose the wider type, because it contains
    2213              :      more information.  */
    2214        23932 :   else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
    2215              :                             outer_type, false, false))
    2216              :     {
    2217         3886 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2218            0 :         fprintf (dump_file, "Second type contain the first as a field\n");
    2219              : 
    2220         3886 :       if (maybe_derived_type)
    2221              :         {
    2222         3426 :           outer_type = ctx.outer_type;
    2223         3426 :           maybe_derived_type = ctx.maybe_derived_type;
    2224         3426 :           offset = ctx.offset;
    2225         3426 :           dynamic = ctx.dynamic;
    2226         3426 :           updated = true;
    2227              :         }
    2228              : 
    2229              :       /* If we do not know how the context is being used, we cannot
    2230              :          clear MAYBE_IN_CONSTRUCTION because it may be offseted
    2231              :          to other component of OUTER_TYPE later and we know nothing
    2232              :          about it.  */
    2233         3886 :       if (otr_type && maybe_in_construction
    2234            0 :           && !ctx.maybe_in_construction)
    2235              :         {
    2236            0 :           maybe_in_construction = false;
    2237            0 :           updated = true;
    2238              :         }
    2239              :     }
    2240        20046 :   else if (contains_type_p (outer_type, offset - ctx.offset,
    2241              :                             ctx.outer_type, false, false))
    2242              :     {
    2243           68 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2244            0 :         fprintf (dump_file, "First type contain the second as a field\n");
    2245              : 
    2246           68 :       if (otr_type && maybe_in_construction
    2247            0 :           && !ctx.maybe_in_construction)
    2248              :         {
    2249            0 :           maybe_in_construction = false;
    2250            0 :           updated = true;
    2251              :         }
    2252              :     }
    2253              :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2254        19978 :   else if (contains_type_p (ctx.outer_type,
    2255        19978 :                             ctx.offset - offset, outer_type, false, true))
    2256              :     {
    2257         9190 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2258           12 :         fprintf (dump_file, "First type is base of second\n");
    2259         9190 :       if (!maybe_derived_type)
    2260              :         {
    2261         4442 :           if (!ctx.maybe_in_construction
    2262         4442 :               && types_odr_comparable (outer_type, ctx.outer_type))
    2263              :             {
    2264            0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2265            0 :                 fprintf (dump_file, "Second context does not permit base -> invalid\n");
    2266            0 :               goto invalidate;
    2267              :             }
    2268              :         }
    2269              :       /* Pick variant deeper in the hierarchy.  */
    2270              :       else
    2271              :         {
    2272         4748 :           outer_type = ctx.outer_type;
    2273         4748 :           maybe_in_construction = ctx.maybe_in_construction;
    2274         4748 :           maybe_derived_type = ctx.maybe_derived_type;
    2275         4748 :           offset = ctx.offset;
    2276         4748 :           dynamic = ctx.dynamic;
    2277         4748 :           updated = true;
    2278              :         }
    2279              :     }
    2280              :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2281        10788 :   else if (contains_type_p (outer_type,
    2282        10788 :                             offset - ctx.offset, ctx.outer_type, false, true))
    2283              :     {
    2284        10673 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2285           50 :         fprintf (dump_file, "Second type is base of first\n");
    2286        10673 :       if (!ctx.maybe_derived_type)
    2287              :         {
    2288          139 :           if (!maybe_in_construction
    2289          139 :               && types_odr_comparable (outer_type, ctx.outer_type))
    2290              :             {
    2291            0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2292            0 :                 fprintf (dump_file, "First context does not permit base -> invalid\n");
    2293            0 :               goto invalidate;
    2294              :             }
    2295              :           /* Pick the base type.  */
    2296          139 :           else if (maybe_in_construction)
    2297              :             {
    2298          139 :               outer_type = ctx.outer_type;
    2299          139 :               maybe_in_construction = ctx.maybe_in_construction;
    2300          139 :               maybe_derived_type = ctx.maybe_derived_type;
    2301          139 :               offset = ctx.offset;
    2302          139 :               dynamic = ctx.dynamic;
    2303          139 :               updated = true;
    2304              :             }
    2305              :         }
    2306              :     }
    2307              :   /* TODO handle merging using hierarchy. */
    2308          115 :   else if (dump_file && (dump_flags & TDF_DETAILS))
    2309            3 :     fprintf (dump_file, "Giving up on merge\n");
    2310              : 
    2311       264998 :   updated |= combine_speculation_with (ctx.speculative_outer_type,
    2312              :                                        ctx.speculative_offset,
    2313       132499 :                                        ctx.speculative_maybe_derived_type,
    2314              :                                        otr_type);
    2315              : 
    2316       132499 :   if (updated && dump_file && (dump_flags & TDF_DETAILS))
    2317              :     {
    2318           33 :       fprintf (dump_file, "Updated as:                      ");
    2319           33 :       dump (dump_file);
    2320           33 :       fprintf (dump_file, "\n");
    2321              :     }
    2322              :   return updated;
    2323              : 
    2324            0 : invalidate:
    2325            0 :   invalid = true;
    2326            0 :   clear_speculation ();
    2327            0 :   clear_outer_type ();
    2328            0 :   return true;
    2329              : }
    2330              : 
    2331              : /* Take non-speculative info, merge it with speculative and clear speculation.
    2332              :    Used when we no longer manage to keep track of actual outer type, but we
    2333              :    think it is still there.
    2334              : 
    2335              :    If OTR_TYPE is set, the transformation can be done more effectively assuming
    2336              :    that context is going to be used only that way.  */
    2337              : 
    2338              : void
    2339        95528 : ipa_polymorphic_call_context::make_speculative (tree otr_type)
    2340              : {
    2341        95528 :   tree spec_outer_type = outer_type;
    2342        95528 :   HOST_WIDE_INT spec_offset = offset;
    2343        95528 :   bool spec_maybe_derived_type = maybe_derived_type;
    2344              : 
    2345        95528 :   if (invalid)
    2346              :     {
    2347            0 :       invalid = false;
    2348            0 :       clear_outer_type ();
    2349            0 :       clear_speculation ();
    2350            0 :       return;
    2351              :     }
    2352        95528 :   if (!outer_type)
    2353              :     return;
    2354        30083 :   clear_outer_type ();
    2355        30083 :   combine_speculation_with (spec_outer_type, spec_offset,
    2356              :                             spec_maybe_derived_type,
    2357              :                             otr_type);
    2358              : }
    2359              : 
    2360              : /* Use when we cannot track dynamic type change.  This speculatively assume
    2361              :    type change is not happening.  */
    2362              : 
    2363              : void
    2364       116122 : ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
    2365              :                                                             tree otr_type)
    2366              : {
    2367       116122 :   if (dynamic)
    2368              :     {
    2369              :       /* See if existing speculation was inconsistent before type change.
    2370              :          If so drop it first, so we do not lose track about it being
    2371              :          impossible.  */
    2372        95492 :       if (speculative_outer_type
    2373        95492 :           && !speculation_consistent_p (speculative_outer_type,
    2374              :                                         speculative_offset,
    2375              :                                         speculative_maybe_derived_type,
    2376              :                                         otr_type))
    2377         7683 :         clear_speculation ();
    2378        95492 :       make_speculative (otr_type);
    2379              :     }
    2380        20630 :   else if (in_poly_cdtor)
    2381        11833 :     maybe_in_construction = true;
    2382       116122 : }
    2383              : 
    2384              : /* Return TRUE if this context conveys the same information as OTHER.  */
    2385              : 
    2386              : bool
    2387       126587 : ipa_polymorphic_call_context::equal_to
    2388              :     (const ipa_polymorphic_call_context &x) const
    2389              : {
    2390       126587 :   if (useless_p ())
    2391          122 :     return x.useless_p ();
    2392       126465 :   if (invalid)
    2393            0 :     return x.invalid;
    2394       237867 :   if (x.useless_p () || x.invalid)
    2395              :     return false;
    2396              : 
    2397       126454 :   if (outer_type)
    2398              :     {
    2399        17039 :       if (!x.outer_type
    2400        16739 :           || !types_odr_comparable (outer_type, x.outer_type)
    2401        16739 :           || !types_same_for_odr (outer_type, x.outer_type)
    2402        16434 :           || offset != x.offset
    2403        16413 :           || maybe_in_construction != x.maybe_in_construction
    2404        16405 :           || maybe_derived_type != x.maybe_derived_type
    2405        33385 :           || dynamic != x.dynamic)
    2406          799 :         return false;
    2407              :     }
    2408       109415 :   else if (x.outer_type)
    2409              :     return false;
    2410              : 
    2411              : 
    2412       125046 :   if (speculative_outer_type
    2413       235737 :       && speculation_consistent_p (speculative_outer_type, speculative_offset,
    2414       110691 :                                    speculative_maybe_derived_type, NULL_TREE))
    2415              :     {
    2416       107629 :       if (!x.speculative_outer_type)
    2417              :         return false;
    2418              : 
    2419       107629 :       if (!types_odr_comparable (speculative_outer_type,
    2420              :                                  x.speculative_outer_type)
    2421       107629 :           || !types_same_for_odr  (speculative_outer_type,
    2422       107629 :                                    x.speculative_outer_type)
    2423       106958 :           || speculative_offset != x.speculative_offset
    2424       214523 :           || speculative_maybe_derived_type != x.speculative_maybe_derived_type)
    2425          738 :         return false;
    2426              :     }
    2427        17417 :   else if (x.speculative_outer_type
    2428        20499 :            && x.speculation_consistent_p (x.speculative_outer_type,
    2429         3082 :                                           x.speculative_offset,
    2430         3082 :                                           x.speculative_maybe_derived_type,
    2431              :                                           NULL))
    2432              :     return false;
    2433              : 
    2434              :   return true;
    2435              : }
    2436              : 
    2437              : /* Modify context to be strictly less restrictive than CTX.  */
    2438              : 
    2439              : bool
    2440         1379 : ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx,
    2441              :                                          tree otr_type)
    2442              : {
    2443         1379 :   bool updated = false;
    2444              : 
    2445         3740 :   if (useless_p () || ctx.invalid)
    2446              :     return false;
    2447              : 
    2448              :   /* Restricting context to inner type makes merging easier, however do not
    2449              :      do that unless we know how the context is used (OTR_TYPE is non-NULL)  */
    2450         1379 :   if (otr_type && !useless_p () && !ctx.useless_p ())
    2451              :     {
    2452            0 :       restrict_to_inner_class (otr_type);
    2453            0 :       ctx.restrict_to_inner_class (otr_type);
    2454            0 :       if(invalid)
    2455              :         return false;
    2456              :     }
    2457              : 
    2458         1379 :   if (equal_to (ctx))
    2459              :     return false;
    2460              : 
    2461           78 :   if (ctx.useless_p () || invalid)
    2462              :     {
    2463           11 :       *this = ctx;
    2464           11 :       return true;
    2465              :     }
    2466              : 
    2467           59 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2468              :     {
    2469            0 :       fprintf (dump_file, "Polymorphic call context meet:");
    2470            0 :       dump (dump_file);
    2471            0 :       fprintf (dump_file, "With context:                    ");
    2472            0 :       ctx.dump (dump_file);
    2473            0 :       if (otr_type)
    2474              :         {
    2475            0 :           fprintf (dump_file, "To be used with type:            ");
    2476            0 :           print_generic_expr (dump_file, otr_type, TDF_SLIM);
    2477            0 :           fprintf (dump_file, "\n");
    2478              :         }
    2479              :     }
    2480              : 
    2481           59 :   if (!dynamic && ctx.dynamic)
    2482              :     {
    2483            4 :       dynamic = true;
    2484            4 :       updated = true;
    2485              :     }
    2486              : 
    2487              :   /* If a certain context is known to be invalid, we can move to comparing
    2488              :      speculation.  Because the second context might be a certain one which can
    2489              :      be met with the speculation of the first, make it speculative.  */
    2490           59 :   if (!outer_type)
    2491           28 :     ctx.make_speculative ();
    2492           31 :   else if (!ctx.outer_type)
    2493              :     {
    2494            8 :       make_speculative ();
    2495            8 :       updated = true;
    2496              :     }
    2497              :   /* If types are known to be same, merging is quite easy.  */
    2498           23 :   else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
    2499              :     {
    2500           23 :       if (offset != ctx.offset
    2501            0 :           && TYPE_SIZE (outer_type)
    2502           23 :           && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
    2503              :         {
    2504            0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2505            0 :             fprintf (dump_file, "Outer types match, offset mismatch -> clearing\n");
    2506            0 :           clear_outer_type ();
    2507            0 :           return true;
    2508              :         }
    2509           23 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2510            0 :         fprintf (dump_file, "Outer types match, merging flags\n");
    2511           23 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2512              :         {
    2513            0 :           updated = true;
    2514            0 :           maybe_in_construction = true;
    2515              :         }
    2516           23 :       if (!maybe_derived_type && ctx.maybe_derived_type)
    2517              :         {
    2518            4 :           updated = true;
    2519            4 :           maybe_derived_type = true;
    2520              :         }
    2521           23 :       if (!dynamic && ctx.dynamic)
    2522              :         {
    2523            0 :           updated = true;
    2524            0 :           dynamic = true;
    2525              :         }
    2526              :     }
    2527              :   /* See if one type contains the other as a field (not base).  */
    2528            0 :   else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
    2529              :                             outer_type, false, false))
    2530              :     {
    2531            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2532            0 :         fprintf (dump_file, "Second type contain the first as a field\n");
    2533              : 
    2534              :       /* The second type is more specified, so we keep the first.
    2535              :          We need to set DYNAMIC flag to avoid declaring context INVALID
    2536              :          of OFFSET ends up being out of range.  */
    2537            0 :       if (!dynamic
    2538            0 :           && (ctx.dynamic
    2539            0 :               || (!otr_type
    2540            0 :                   && (!TYPE_SIZE (ctx.outer_type)
    2541            0 :                       || !TYPE_SIZE (outer_type)
    2542            0 :                       || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
    2543            0 :                                            TYPE_SIZE (outer_type), 0)))))
    2544              :         {
    2545            0 :           dynamic = true;
    2546            0 :           updated = true;
    2547              :         }
    2548              :     }
    2549            0 :   else if (contains_type_p (outer_type, offset - ctx.offset,
    2550              :                             ctx.outer_type, false, false))
    2551              :     {
    2552            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2553            0 :         fprintf (dump_file, "First type contain the second as a field\n");
    2554              : 
    2555            0 :       if (!dynamic
    2556            0 :           && (ctx.dynamic
    2557            0 :               || (!otr_type
    2558            0 :                   && (!TYPE_SIZE (ctx.outer_type)
    2559            0 :                       || !TYPE_SIZE (outer_type)
    2560            0 :                       || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
    2561            0 :                                            TYPE_SIZE (outer_type), 0)))))
    2562              :         dynamic = true;
    2563            0 :       outer_type = ctx.outer_type;
    2564            0 :       offset = ctx.offset;
    2565            0 :       dynamic = ctx.dynamic;
    2566            0 :       maybe_in_construction = ctx.maybe_in_construction;
    2567            0 :       maybe_derived_type = ctx.maybe_derived_type;
    2568            0 :       updated = true;
    2569              :     }
    2570              :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2571            0 :   else if (contains_type_p (ctx.outer_type,
    2572            0 :                             ctx.offset - offset, outer_type, false, true))
    2573              :     {
    2574            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2575            0 :         fprintf (dump_file, "First type is base of second\n");
    2576            0 :       if (!maybe_derived_type)
    2577              :         {
    2578            0 :           maybe_derived_type = true;
    2579            0 :           updated = true;
    2580              :         }
    2581            0 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2582              :         {
    2583            0 :           maybe_in_construction = true;
    2584            0 :           updated = true;
    2585              :         }
    2586            0 :       if (!dynamic && ctx.dynamic)
    2587              :         {
    2588            0 :           dynamic = true;
    2589            0 :           updated = true;
    2590              :         }
    2591              :     }
    2592              :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2593            0 :   else if (contains_type_p (outer_type,
    2594            0 :                             offset - ctx.offset, ctx.outer_type, false, true))
    2595              :     {
    2596            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2597            0 :         fprintf (dump_file, "Second type is base of first\n");
    2598            0 :       outer_type = ctx.outer_type;
    2599            0 :       offset = ctx.offset;
    2600            0 :       updated = true;
    2601            0 :       if (!maybe_derived_type)
    2602            0 :         maybe_derived_type = true;
    2603            0 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2604            0 :         maybe_in_construction = true;
    2605            0 :       if (!dynamic && ctx.dynamic)
    2606            0 :         dynamic = true;
    2607              :     }
    2608              :   /* TODO handle merging using hierarchy. */
    2609              :   else
    2610              :     {
    2611            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2612            0 :         fprintf (dump_file, "Giving up on meet\n");
    2613            0 :       clear_outer_type ();
    2614            0 :       updated = true;
    2615              :     }
    2616              : 
    2617          118 :   updated |= meet_speculation_with (ctx.speculative_outer_type,
    2618              :                                     ctx.speculative_offset,
    2619           59 :                                     ctx.speculative_maybe_derived_type,
    2620              :                                     otr_type);
    2621              : 
    2622           59 :   if (updated && dump_file && (dump_flags & TDF_DETAILS))
    2623              :     {
    2624            0 :       fprintf (dump_file, "Updated as:                      ");
    2625            0 :       dump (dump_file);
    2626            0 :       fprintf (dump_file, "\n");
    2627              :     }
    2628              :   return updated;
    2629              : }
        

Generated by: LCOV version 2.4-beta

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