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

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.