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

Generated by: LCOV version 2.4-beta

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