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