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