Branch data Line data Source code
1 : : /* Analysis of polymorphic call context.
2 : : Copyright (C) 2013-2025 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 : 34352930 : contains_polymorphic_type_p (const_tree type)
54 : : {
55 : 39445788 : type = TYPE_MAIN_VARIANT (type);
56 : :
57 : 39445788 : if (RECORD_OR_UNION_TYPE_P (type))
58 : : {
59 : 9103669 : if (TYPE_BINFO (type)
60 : 9103669 : && polymorphic_type_binfo_p (TYPE_BINFO (type)))
61 : : return true;
62 : 395881209 : for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
63 : 388125494 : if (TREE_CODE (fld) == FIELD_DECL
64 : 30567945 : && !DECL_ARTIFICIAL (fld)
65 : 416504778 : && contains_polymorphic_type_p (TREE_TYPE (fld)))
66 : : return true;
67 : : return false;
68 : : }
69 : 30342119 : if (TREE_CODE (type) == ARRAY_TYPE)
70 : 5092858 : 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 : 112005 : possible_placement_new (tree type, tree expected_type,
82 : : HOST_WIDE_INT cur_offset)
83 : : {
84 : 112005 : if (cur_offset < 0)
85 : : return true;
86 : 108395 : return ((TREE_CODE (type) != RECORD_TYPE
87 : 14004 : || !TYPE_BINFO (type)
88 : 14044 : || cur_offset >= POINTER_SIZE
89 : 11539 : || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
90 : 122333 : && (!TYPE_SIZE (type)
91 : 108329 : || !tree_fits_shwi_p (TYPE_SIZE (type))
92 : 216658 : || (cur_offset
93 : 108329 : + (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
94 : 97757 : : POINTER_SIZE)
95 : 108329 : <= 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 : 1992823 : ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
130 : : bool consider_placement_new,
131 : : bool consider_bases)
132 : : {
133 : 1992823 : tree type = outer_type;
134 : 1992823 : HOST_WIDE_INT cur_offset = offset;
135 : 1992823 : bool speculative = false;
136 : 1992823 : bool size_unknown = false;
137 : 1992823 : unsigned HOST_WIDE_INT otr_type_size = POINTER_SIZE;
138 : :
139 : : /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set. */
140 : 1992823 : if (!outer_type)
141 : : {
142 : 77042 : clear_outer_type (otr_type);
143 : 77042 : type = otr_type;
144 : 77042 : 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 : 1915781 : else if (TYPE_SIZE (outer_type)
156 : 1915758 : && tree_fits_shwi_p (TYPE_SIZE (outer_type))
157 : 1915758 : && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
158 : 3831539 : && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
159 : : {
160 : 10 : bool der = maybe_derived_type; /* clear_outer_type will reset it. */
161 : 10 : bool dyn = dynamic;
162 : 10 : clear_outer_type (otr_type);
163 : 10 : type = otr_type;
164 : 10 : 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 : 10 : if (!der && !dyn)
171 : : {
172 : 10 : clear_speculation ();
173 : 10 : invalid = true;
174 : 10 : return false;
175 : : }
176 : : }
177 : :
178 : 1890936 : if (otr_type && TYPE_SIZE (otr_type)
179 : 3883744 : && tree_fits_shwi_p (TYPE_SIZE (otr_type)))
180 : 1890931 : otr_type_size = tree_to_uhwi (TYPE_SIZE (otr_type));
181 : :
182 : 1992813 : if (!type || offset < 0)
183 : 3610 : 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 : 2478758 : while (true)
191 : : {
192 : 2478758 : unsigned HOST_WIDE_INT pos, size;
193 : 2478758 : 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 : 2478758 : if (TYPE_SIZE (type)
200 : 2478735 : && tree_fits_shwi_p (TYPE_SIZE (type))
201 : 4957493 : && 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 : 2478758 : if ((otr_type
208 : 2152259 : && types_odr_comparable (type, otr_type)
209 : 2152259 : && types_same_for_odr (type, otr_type))
210 : 2478758 : || (!otr_type
211 : 326499 : && TREE_CODE (type) == RECORD_TYPE
212 : 242392 : && TYPE_BINFO (type)
213 : 241662 : && polymorphic_type_binfo_p (TYPE_BINFO (type))))
214 : : {
215 : 1511850 : if (speculative)
216 : : {
217 : : /* If we did not match the offset, just give up on speculation. */
218 : 9354 : if (cur_offset != 0
219 : : /* Also check if speculation did not end up being same as
220 : : non-speculation. */
221 : 9354 : || (types_must_be_same_for_odr (speculative_outer_type,
222 : : outer_type)
223 : 48 : && (maybe_derived_type
224 : 48 : == speculative_maybe_derived_type)))
225 : 0 : clear_speculation ();
226 : 9354 : 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 : 1499836 : if (otr_type && TREE_CODE (outer_type) == RECORD_TYPE
233 : 1499836 : && (!in_lto_p || odr_type_p (outer_type))
234 : 1499836 : && type_with_linkage_p (outer_type)
235 : 3002332 : && type_known_to_have_no_derivations_p (outer_type))
236 : 7633 : 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 : 1502496 : if (cur_offset != 0)
244 : 2136 : goto no_useful_type_info;
245 : : /* If we determined type precisely or we have no clue on
246 : : speculation, we are done. */
247 : 1165698 : if (!maybe_derived_type || !speculative_outer_type
248 : 1579702 : || !speculation_consistent_p (speculative_outer_type,
249 : : speculative_offset,
250 : : speculative_maybe_derived_type,
251 : : otr_type))
252 : : {
253 : 1491009 : clear_speculation ();
254 : 1491009 : return true;
255 : : }
256 : : /* Otherwise look into speculation now. */
257 : : else
258 : : {
259 : 9351 : speculative = true;
260 : 9351 : type = speculative_outer_type;
261 : 9351 : cur_offset = speculative_offset;
262 : 9351 : continue;
263 : : }
264 : : }
265 : : }
266 : :
267 : : /* Walk fields and find corresponding on at OFFSET. */
268 : 966908 : if (TREE_CODE (type) == RECORD_TYPE)
269 : : {
270 : 13900351 : for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
271 : : {
272 : 25881081 : if (TREE_CODE (fld) != FIELD_DECL
273 : 13647178 : || TREE_TYPE (fld) == error_mark_node)
274 : 12233903 : continue;
275 : :
276 : 1413275 : pos = int_bit_position (fld);
277 : 1413275 : if (pos > (unsigned HOST_WIDE_INT)cur_offset)
278 : 360955 : continue;
279 : :
280 : : /* Do not consider vptr itself. Not even for placement new. */
281 : 1022381 : if (!pos && DECL_ARTIFICIAL (fld)
282 : 819219 : && POINTER_TYPE_P (TREE_TYPE (fld))
283 : 178835 : && TYPE_BINFO (type)
284 : 1231155 : && polymorphic_type_binfo_p (TYPE_BINFO (type)))
285 : 178835 : continue;
286 : :
287 : 873485 : if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
288 : 0 : goto no_useful_type_info;
289 : 873485 : 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 : 873485 : if (pos <= (unsigned HOST_WIDE_INT)cur_offset
301 : 1746970 : && (pos + size) >= (unsigned HOST_WIDE_INT)cur_offset
302 : 894370 : + POINTER_SIZE
303 : 682010 : && (!otr_type
304 : 453792 : || !TYPE_SIZE (TREE_TYPE (fld))
305 : 453792 : || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld)))
306 : 453792 : || (pos + tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld))))
307 : 453792 : >= cur_offset + otr_type_size))
308 : : break;
309 : : }
310 : :
311 : 872326 : if (!fld)
312 : 253173 : goto no_useful_type_info;
313 : :
314 : 619153 : type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
315 : 619153 : cur_offset -= pos;
316 : : /* DECL_ARTIFICIAL represents a basetype. */
317 : 619153 : if (!DECL_ARTIFICIAL (fld))
318 : : {
319 : 209782 : if (!speculative)
320 : : {
321 : 209379 : outer_type = type;
322 : 209379 : offset = cur_offset;
323 : : /* As soon as we see an field containing the type,
324 : : we know we are not looking for derivations. */
325 : 209379 : maybe_derived_type = false;
326 : : }
327 : : else
328 : : {
329 : 403 : speculative_outer_type = type;
330 : 403 : speculative_offset = cur_offset;
331 : 403 : speculative_maybe_derived_type = false;
332 : : }
333 : : }
334 : 409371 : else if (!consider_bases)
335 : 138978 : goto no_useful_type_info;
336 : : }
337 : 94582 : else if (TREE_CODE (type) == ARRAY_TYPE)
338 : : {
339 : 10474 : 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 : 10474 : if (!TYPE_SIZE (subtype)
345 : 10474 : || !tree_fits_shwi_p (TYPE_SIZE (subtype))
346 : 10474 : || tree_to_shwi (TYPE_SIZE (subtype)) <= 0
347 : 20948 : || !contains_polymorphic_type_p (subtype))
348 : 10091 : 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 : 84108 : no_useful_type_info:
378 : 5 : if (maybe_derived_type && !speculative
379 : 5 : && TREE_CODE (outer_type) == RECORD_TYPE
380 : 5 : && TREE_CODE (otr_type) == RECORD_TYPE
381 : 5 : && TYPE_BINFO (otr_type)
382 : 5 : && !offset
383 : 492458 : && get_binfo_at_offset (TYPE_BINFO (otr_type), 0, outer_type))
384 : : {
385 : 5 : clear_outer_type (otr_type);
386 : 5 : if (!speculative_outer_type
387 : 5 : || !speculation_consistent_p (speculative_outer_type,
388 : : speculative_offset,
389 : 0 : speculative_maybe_derived_type,
390 : : otr_type))
391 : 5 : clear_speculation ();
392 : 5 : 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 : 492448 : if (!speculative
405 : 492448 : && consider_placement_new
406 : 492448 : && (size_unknown || !type || maybe_derived_type
407 : 112005 : || 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 : 108750 : if (!speculative)
416 : : {
417 : 108750 : clear_outer_type (otr_type);
418 : 108750 : if (!speculative_outer_type
419 : 108755 : || !speculation_consistent_p (speculative_outer_type,
420 : : speculative_offset,
421 : 5 : speculative_maybe_derived_type,
422 : : otr_type))
423 : 108747 : clear_speculation ();
424 : 108750 : if (speculative_outer_type)
425 : : {
426 : 3 : speculative = true;
427 : 3 : type = speculative_outer_type;
428 : 3 : 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 : 383698 : clear_speculation ();
442 : 383698 : if (speculative)
443 : : return true;
444 : 383698 : clear_outer_type (otr_type);
445 : 383698 : invalid = true;
446 : 383698 : 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 : 682399 : 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 : 682399 : ipa_polymorphic_call_context context;
465 : :
466 : : /* Check that type is within range. */
467 : 682399 : 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 : 676711 : context.offset = offset;
477 : 676711 : context.outer_type = TYPE_MAIN_VARIANT (outer_type);
478 : 676711 : context.maybe_derived_type = false;
479 : 676711 : context.dynamic = false;
480 : 676711 : return context.restrict_to_inner_class (otr_type, consider_placement_new,
481 : 676711 : 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 : 55989770 : polymorphic_ctor_dtor_p (tree fn, bool check_clones)
490 : : {
491 : 55989770 : if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
492 : 93122026 : || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
493 : : {
494 : 38570635 : 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 : 38534471 : fn = DECL_ABSTRACT_ORIGIN (fn);
500 : 38534471 : if (!fn
501 : 26830573 : || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
502 : 55628483 : || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
503 : : return NULL_TREE;
504 : : }
505 : :
506 : 17419426 : 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 : 164243577 : inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
517 : : {
518 : 164243577 : tree fn = block_ultimate_origin (block);
519 : 164243577 : if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
520 : : return NULL_TREE;
521 : :
522 : 45164900 : 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 : 27499424 : decl_maybe_in_construction_p (tree base, tree outer_type,
544 : : gimple *call, tree function)
545 : : {
546 : 27499424 : if (outer_type)
547 : 44551 : outer_type = TYPE_MAIN_VARIANT (outer_type);
548 : 27499424 : 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 : 27499424 : 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 : 36270 : if ((!base || !auto_var_in_fn_p (base, function))
560 : 27462998 : && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
561 : : return false;
562 : :
563 : 27184034 : bool check_clones = !base || is_global_var (base);
564 : 145500132 : for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
565 : 59158049 : block = BLOCK_SUPERCONTEXT (block))
566 : 59180883 : if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones))
567 : : {
568 : 286553 : tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
569 : :
570 : 286553 : if (!outer_type || !types_odr_comparable (type, outer_type))
571 : : {
572 : 282317 : if (TREE_CODE (type) == RECORD_TYPE
573 : 280902 : && TYPE_BINFO (type)
574 : 560822 : && polymorphic_type_binfo_p (TYPE_BINFO (type)))
575 : : return true;
576 : : }
577 : 4236 : else if (types_same_for_odr (type, outer_type))
578 : : return true;
579 : : }
580 : :
581 : 27161200 : if (!base || (VAR_P (base) && is_global_var (base)))
582 : : {
583 : 27132278 : if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
584 : 34550837 : || (!DECL_CXX_CONSTRUCTOR_P (function)
585 : 6235833 : && !DECL_CXX_DESTRUCTOR_P (function)))
586 : : {
587 : 25448676 : 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 : 78656 : function = DECL_ABSTRACT_ORIGIN (function);
592 : 78656 : if (!function
593 : 78656 : || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
594 : 122991 : || (!DECL_CXX_CONSTRUCTOR_P (function)
595 : 44303 : && !DECL_CXX_DESTRUCTOR_P (function)))
596 : : return false;
597 : : }
598 : 1683634 : tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (function));
599 : 1683634 : if (!outer_type || !types_odr_comparable (type, outer_type))
600 : : {
601 : 1683598 : if (TREE_CODE (type) == RECORD_TYPE
602 : 1682359 : && TYPE_BINFO (type)
603 : 3357400 : && 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 : 1217 : ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
617 : : {
618 : 1217 : fprintf (f, " ");
619 : 1217 : if (invalid)
620 : 0 : fprintf (f, "Call is known to be undefined");
621 : : else
622 : : {
623 : 1217 : if (useless_p ())
624 : 0 : fprintf (f, "nothing known");
625 : 1217 : if (outer_type || offset)
626 : : {
627 : 1376 : fprintf (f, "Outer type%s:", dynamic ? " (dynamic)" : "");
628 : 1072 : print_generic_expr (f, outer_type, TDF_SLIM);
629 : 1072 : if (maybe_derived_type)
630 : 599 : fprintf (f, " (or a derived type)");
631 : 1072 : if (maybe_in_construction)
632 : 160 : fprintf (f, " (maybe in construction)");
633 : 1072 : fprintf (f, " offset " HOST_WIDE_INT_PRINT_DEC,
634 : 1072 : offset);
635 : : }
636 : 1217 : if (speculative_outer_type)
637 : : {
638 : 294 : if (outer_type || offset)
639 : 149 : fprintf (f, " ");
640 : 294 : fprintf (f, "Speculative outer type:");
641 : 294 : print_generic_expr (f, speculative_outer_type, TDF_SLIM);
642 : 294 : if (speculative_maybe_derived_type)
643 : 267 : fprintf (f, " (or a derived type)");
644 : 294 : fprintf (f, " at offset " HOST_WIDE_INT_PRINT_DEC,
645 : 294 : speculative_offset);
646 : : }
647 : : }
648 : 1217 : if (newline)
649 : 1046 : fprintf(f, "\n");
650 : 1217 : }
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 : 2882 : ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
664 : : {
665 : 2882 : struct bitpack_d bp = bitpack_create (ob->main_stream);
666 : :
667 : 2882 : bp_pack_value (&bp, invalid, 1);
668 : 2882 : bp_pack_value (&bp, maybe_in_construction, 1);
669 : 2882 : bp_pack_value (&bp, maybe_derived_type, 1);
670 : 2882 : bp_pack_value (&bp, speculative_maybe_derived_type, 1);
671 : 2882 : bp_pack_value (&bp, dynamic, 1);
672 : 2882 : bp_pack_value (&bp, outer_type != NULL, 1);
673 : 2882 : bp_pack_value (&bp, offset != 0, 1);
674 : 2882 : bp_pack_value (&bp, speculative_outer_type != NULL, 1);
675 : 2882 : streamer_write_bitpack (&bp);
676 : :
677 : 2882 : if (outer_type != NULL)
678 : 1345 : stream_write_tree (ob, outer_type, true);
679 : 2882 : if (offset)
680 : 550 : streamer_write_hwi (ob, offset);
681 : 2882 : if (speculative_outer_type != NULL)
682 : : {
683 : 1033 : stream_write_tree (ob, speculative_outer_type, true);
684 : 1033 : streamer_write_hwi (ob, speculative_offset);
685 : : }
686 : : else
687 : 1849 : gcc_assert (!speculative_offset);
688 : 2882 : }
689 : :
690 : : /* Stream in the context from IB and DATA_IN. */
691 : :
692 : : void
693 : 1390 : ipa_polymorphic_call_context::stream_in (class lto_input_block *ib,
694 : : class data_in *data_in)
695 : : {
696 : 1390 : struct bitpack_d bp = streamer_read_bitpack (ib);
697 : :
698 : 1390 : invalid = bp_unpack_value (&bp, 1);
699 : 1390 : maybe_in_construction = bp_unpack_value (&bp, 1);
700 : 1390 : maybe_derived_type = bp_unpack_value (&bp, 1);
701 : 1390 : speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
702 : 1390 : dynamic = bp_unpack_value (&bp, 1);
703 : 1390 : bool outer_type_p = bp_unpack_value (&bp, 1);
704 : 1390 : bool offset_p = bp_unpack_value (&bp, 1);
705 : 1390 : bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
706 : :
707 : 1390 : if (outer_type_p)
708 : 668 : outer_type = stream_read_tree (ib, data_in);
709 : : else
710 : 722 : outer_type = NULL;
711 : 1390 : if (offset_p)
712 : 390 : offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
713 : : else
714 : 1000 : offset = 0;
715 : 1390 : if (speculative_outer_type_p)
716 : : {
717 : 529 : speculative_outer_type = stream_read_tree (ib, data_in);
718 : 529 : 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 : 1390 : }
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 : 1114337 : ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off)
732 : : {
733 : 1114337 : gcc_assert (DECL_P (base));
734 : 1114337 : clear_speculation ();
735 : :
736 : 1114337 : if (!contains_polymorphic_type_p (TREE_TYPE (base)))
737 : : {
738 : 1068957 : clear_outer_type ();
739 : 1068957 : offset = off;
740 : 1068957 : return;
741 : : }
742 : 45380 : outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
743 : 45380 : 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 : 45380 : maybe_in_construction = true;
750 : 45380 : maybe_derived_type = false;
751 : 45380 : 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 : 10336 : ipa_polymorphic_call_context::set_by_invariant (tree cst,
761 : : tree otr_type,
762 : : HOST_WIDE_INT off)
763 : : {
764 : 10336 : poly_int64 offset2, size, max_size;
765 : 10336 : bool reverse;
766 : 10336 : tree base;
767 : :
768 : 10336 : invalid = false;
769 : 10336 : clear_outer_type (otr_type);
770 : :
771 : 10336 : if (TREE_CODE (cst) != ADDR_EXPR)
772 : : return false;
773 : :
774 : 4516 : cst = TREE_OPERAND (cst, 0);
775 : 4516 : base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
776 : 4516 : 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 : 4510 : if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type))
782 : : return false;
783 : :
784 : 2312 : set_by_decl (base, off);
785 : 2312 : 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 : 5918639 : walk_ssa_copies (tree op, hash_set<tree> **global_visited = NULL)
795 : : {
796 : 5918639 : hash_set <tree> *visited = NULL;
797 : 5918639 : STRIP_NOPS (op);
798 : 5918639 : while (TREE_CODE (op) == SSA_NAME
799 : 3003314 : && !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 : 2013639 : && !name_registered_for_update_p (op)
803 : 8285173 : && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
804 : 395193 : || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
805 : : {
806 : 1700685 : if (global_visited)
807 : : {
808 : 1172233 : if (!*global_visited)
809 : 1094817 : *global_visited = new hash_set<tree>;
810 : 1172233 : if ((*global_visited)->add (op))
811 : 0 : goto done;
812 : : }
813 : : else
814 : : {
815 : 528452 : if (!visited)
816 : 528436 : visited = new hash_set<tree>;
817 : 528452 : 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 : 1700685 : if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
830 : : {
831 : 82239 : gimple *phi = SSA_NAME_DEF_STMT (op);
832 : :
833 : 82239 : if (gimple_phi_num_args (phi) > 2)
834 : 20745 : goto done;
835 : 61494 : if (gimple_phi_num_args (phi) == 1)
836 : 517 : op = gimple_phi_arg_def (phi, 0);
837 : 60977 : else if (integer_zerop (gimple_phi_arg_def (phi, 0)))
838 : 4904 : op = gimple_phi_arg_def (phi, 1);
839 : 56073 : else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
840 : 2660 : op = gimple_phi_arg_def (phi, 0);
841 : : else
842 : 53413 : goto done;
843 : : }
844 : : else
845 : : {
846 : 1618446 : if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
847 : 1273632 : goto done;
848 : 344814 : op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
849 : : }
850 : 352895 : STRIP_NOPS (op);
851 : : }
852 : 5918639 : done:
853 : 5918639 : if (visited)
854 : 528436 : delete (visited);
855 : 5918639 : 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 : 10336 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst,
864 : : tree otr_type,
865 : 10336 : HOST_WIDE_INT off)
866 : : {
867 : 10336 : clear_speculation ();
868 : 10336 : set_by_invariant (cst, otr_type, off);
869 : 10336 : }
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 : 3705070 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
876 : : tree ref,
877 : : gimple *stmt,
878 : 3705070 : tree *instance)
879 : : {
880 : 3705070 : tree otr_type = NULL;
881 : 3705070 : tree base_pointer;
882 : 3705070 : hash_set <tree> *visited = NULL;
883 : :
884 : 3705070 : if (TREE_CODE (ref) == OBJ_TYPE_REF)
885 : : {
886 : 795748 : otr_type = obj_type_ref_class (ref);
887 : 795748 : 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 : 3705070 : clear_speculation ();
894 : 3705070 : clear_outer_type (otr_type);
895 : 3705070 : invalid = false;
896 : :
897 : : /* Walk SSA for outer object. */
898 : 3954735 : while (true)
899 : : {
900 : 3954735 : base_pointer = walk_ssa_copies (base_pointer, &visited);
901 : 3954735 : if (TREE_CODE (base_pointer) == ADDR_EXPR)
902 : : {
903 : 1776236 : HOST_WIDE_INT offset2, size;
904 : 1776236 : bool reverse;
905 : 1776236 : tree base
906 : 1776236 : = get_ref_base_and_extent_hwi (TREE_OPERAND (base_pointer, 0),
907 : : &offset2, &size, &reverse);
908 : 1776236 : if (!base)
909 : : break;
910 : :
911 : 1753506 : combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
912 : 1753506 : offset + offset2,
913 : : true,
914 : : NULL /* Do not change outer type. */);
915 : :
916 : : /* If this is a varying address, punt. */
917 : 1753506 : 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 : 1361698 : offset_int mem_offset;
922 : 1361698 : if (TREE_CODE (base) == MEM_REF
923 : 1361698 : && mem_ref_offset (base).is_constant (&mem_offset))
924 : : {
925 : 249673 : offset_int o = mem_offset * BITS_PER_UNIT;
926 : 249673 : o += offset;
927 : 249673 : o += offset2;
928 : 249673 : if (!wi::fits_shwi_p (o))
929 : : break;
930 : 249665 : base_pointer = TREE_OPERAND (base, 0);
931 : 249665 : offset = o.to_shwi ();
932 : 249665 : outer_type = NULL;
933 : : }
934 : : /* We found base object. In this case the outer_type
935 : : is known. */
936 : 1112025 : else if (DECL_P (base))
937 : : {
938 : 1112025 : if (visited)
939 : 808 : delete (visited);
940 : : /* Only type inconsistent programs can have otr_type that is
941 : : not part of outer type. */
942 : 1112025 : if (otr_type
943 : 1125415 : && !contains_type_p (TREE_TYPE (base),
944 : 13390 : offset + offset2, otr_type))
945 : : {
946 : 0 : invalid = true;
947 : 0 : if (instance)
948 : 0 : *instance = base_pointer;
949 : 1112025 : return;
950 : : }
951 : 1112025 : set_by_decl (base, offset + offset2);
952 : 1112025 : if (outer_type && maybe_in_construction && stmt)
953 : 44551 : maybe_in_construction
954 : 44551 : = decl_maybe_in_construction_p (base,
955 : : outer_type,
956 : : stmt,
957 : : fndecl);
958 : 1112025 : if (instance)
959 : 1102428 : *instance = base;
960 : 1112025 : return;
961 : : }
962 : : else
963 : : break;
964 : : }
965 : : else
966 : : break;
967 : : }
968 : 2178499 : else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
969 : 2178499 : && 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 : 2593045 : if (visited)
986 : 1094009 : delete (visited);
987 : :
988 : : /* Try to determine type of the outer object. */
989 : 2593045 : if (TREE_CODE (base_pointer) == SSA_NAME
990 : 2105572 : && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
991 : 3534831 : && TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL)
992 : : {
993 : : /* See if parameter is THIS pointer of a method. */
994 : 932264 : if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
995 : 1442426 : && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
996 : : {
997 : 386004 : outer_type
998 : 386004 : = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
999 : 386004 : cgraph_node *node = cgraph_node::get (current_function_decl);
1000 : 386004 : 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 : 386004 : thunk_info *info = thunk_info::get (node);
1013 : 386004 : 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 : 386004 : if ((otr_type
1021 : 142353 : && !contains_type_p (outer_type, offset,
1022 : : otr_type))
1023 : 385891 : || !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 : 586747 : || (info && info->virtual_offset_p))
1028 : : {
1029 : 185261 : outer_type = NULL;
1030 : 185261 : if (instance)
1031 : 185014 : *instance = base_pointer;
1032 : 185261 : return;
1033 : : }
1034 : :
1035 : 200743 : 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 : 200743 : if (DECL_CXX_CONSTRUCTOR_P (fndecl)
1041 : 200743 : || DECL_CXX_DESTRUCTOR_P (fndecl))
1042 : : {
1043 : 32421 : maybe_in_construction = true;
1044 : 32421 : maybe_derived_type = false;
1045 : : }
1046 : : else
1047 : : {
1048 : 168322 : maybe_derived_type = true;
1049 : 168322 : maybe_in_construction = false;
1050 : : }
1051 : 200743 : if (instance)
1052 : : {
1053 : 94669 : thunk_info *info = thunk_info::get (node);
1054 : : /* If method is expanded thunk, we need to apply thunk offset
1055 : : to instance pointer. */
1056 : 94669 : if (info && (info->virtual_offset_p || info->fixed_offset))
1057 : 5 : *instance = NULL;
1058 : : else
1059 : 94664 : *instance = base_pointer;
1060 : : }
1061 : 200743 : 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 : 546260 : if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
1067 : : {
1068 : 16158 : outer_type
1069 : 16158 : = 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 : 16158 : 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 : 16158 : else if (!otr_type && !contains_polymorphic_type_p (outer_type))
1082 : : {
1083 : 16070 : outer_type = NULL;
1084 : 16070 : if (instance)
1085 : 16070 : *instance = base_pointer;
1086 : 16070 : 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 : 2190883 : tree base_type = TREE_TYPE (base_pointer);
1097 : :
1098 : 2190883 : if (TREE_CODE (base_pointer) == SSA_NAME
1099 : 1703410 : && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
1100 : 2730507 : && !(TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL
1101 : 9522 : || TREE_CODE (SSA_NAME_VAR (base_pointer)) == RESULT_DECL))
1102 : : {
1103 : 291 : invalid = true;
1104 : 291 : if (instance)
1105 : 169 : *instance = base_pointer;
1106 : 291 : return;
1107 : : }
1108 : 2190592 : if (TREE_CODE (base_pointer) == SSA_NAME
1109 : 1703119 : && SSA_NAME_DEF_STMT (base_pointer)
1110 : 3893711 : && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer)))
1111 : 799732 : base_type = TREE_TYPE (gimple_assign_rhs1
1112 : : (SSA_NAME_DEF_STMT (base_pointer)));
1113 : :
1114 : 2190592 : if (base_type && POINTER_TYPE_P (base_type))
1115 : 2190592 : 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 : 2190592 : if (instance)
1122 : 1711646 : *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 : 6741693 : noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
1163 : : {
1164 : 6741693 : if (is_gimple_assign (stmt))
1165 : : {
1166 : 6640604 : tree lhs = gimple_assign_lhs (stmt);
1167 : :
1168 : 6640604 : if (gimple_clobber_p (stmt))
1169 : : return false;
1170 : 5578284 : if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
1171 : : {
1172 : 4923033 : if (flag_strict_aliasing
1173 : 4923033 : && !POINTER_TYPE_P (TREE_TYPE (lhs)))
1174 : : return false;
1175 : :
1176 : 2315155 : if (TREE_CODE (lhs) == COMPONENT_REF
1177 : 2315155 : && !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 : 1181129 : 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 : 9893177 : for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK;
1193 : 4366995 : block = BLOCK_SUPERCONTEXT (block))
1194 : 4409096 : if (BLOCK_ABSTRACT_ORIGIN (block)
1195 : 4409096 : && TREE_CODE (block_ultimate_origin (block)) == FUNCTION_DECL)
1196 : 42101 : return inlined_polymorphic_ctor_dtor_block_p (block, false);
1197 : 1117086 : return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
1198 : 1117086 : && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
1199 : 67652 : || 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 : 51307 : extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
1209 : : HOST_WIDE_INT *type_offset)
1210 : : {
1211 : 51307 : poly_int64 offset, size, max_size;
1212 : 51307 : tree lhs, rhs, base;
1213 : 51307 : bool reverse;
1214 : :
1215 : 51307 : if (!gimple_assign_single_p (stmt))
1216 : : return NULL_TREE;
1217 : :
1218 : 51244 : lhs = gimple_assign_lhs (stmt);
1219 : 51244 : rhs = gimple_assign_rhs1 (stmt);
1220 : 51244 : if (TREE_CODE (lhs) != COMPONENT_REF
1221 : 51244 : || !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
1222 : : {
1223 : 13665 : if (dump_file)
1224 : 0 : fprintf (dump_file, " LHS is not virtual table.\n");
1225 : 13665 : return NULL_TREE;
1226 : : }
1227 : :
1228 : 37579 : if (tci->vtbl_ptr_ref && operand_equal_p (lhs, tci->vtbl_ptr_ref, 0))
1229 : : ;
1230 : : else
1231 : : {
1232 : 37505 : base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
1233 : 37505 : if (DECL_P (tci->instance))
1234 : : {
1235 : 1492 : if (base != tci->instance)
1236 : : {
1237 : 13 : 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 : 13 : return NULL_TREE;
1246 : : }
1247 : : }
1248 : 36013 : else if (TREE_CODE (base) == MEM_REF)
1249 : : {
1250 : 27061 : if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
1251 : : {
1252 : 15449 : 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 : 15449 : return NULL_TREE;
1261 : : }
1262 : 11612 : if (!integer_zerop (TREE_OPERAND (base, 1)))
1263 : : {
1264 : 1374 : 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 : 1374 : offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
1278 : : }
1279 : : }
1280 : 8952 : else if (!operand_equal_p (tci->instance, base, 0)
1281 : 8952 : || tci->offset)
1282 : : {
1283 : 8952 : 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 : 9002 : return tci->offset > POINTER_SIZE ? error_mark_node : NULL_TREE;
1292 : : }
1293 : 13091 : if (maybe_ne (offset, tci->offset)
1294 : 13491 : || maybe_ne (size, POINTER_SIZE)
1295 : 26582 : || 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 : 13130 : tree vtable;
1314 : 13130 : unsigned HOST_WIDE_INT offset2;
1315 : :
1316 : 13130 : if (!vtable_pointer_value_to_vtable (rhs, &vtable, &offset2))
1317 : : {
1318 : 69 : if (dump_file)
1319 : 4 : fprintf (dump_file, " Failed to lookup binfo\n");
1320 : 69 : return NULL;
1321 : : }
1322 : :
1323 : 13061 : tree binfo = subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
1324 : : offset2, vtable);
1325 : 13061 : 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 : 12900 : *type_offset = tree_to_shwi (BINFO_OFFSET (binfo)) * BITS_PER_UNIT;
1334 : 12900 : return DECL_CONTEXT (vtable);
1335 : : }
1336 : :
1337 : : /* Record dynamic type change of TCI to TYPE. */
1338 : :
1339 : : static void
1340 : 117971 : record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
1341 : : {
1342 : 117971 : 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 bellow
1357 : : happier. */
1358 : 117971 : if (type
1359 : 117971 : && (offset
1360 : 112204 : || (TREE_CODE (type) != RECORD_TYPE
1361 : 112204 : || !TYPE_BINFO (type)
1362 : 111748 : || !polymorphic_type_binfo_p (TYPE_BINFO (type)))))
1363 : : {
1364 : 101904 : ipa_polymorphic_call_context context;
1365 : :
1366 : 101904 : context.offset = offset;
1367 : 101904 : context.outer_type = type;
1368 : 101904 : context.maybe_in_construction = false;
1369 : 101904 : context.maybe_derived_type = false;
1370 : 101904 : 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 : 101904 : if (!context.restrict_to_inner_class (tci->otr_type))
1374 : : {
1375 : 878 : if (dump_file)
1376 : 0 : fprintf (dump_file, " Ignoring; does not contain otr_type\n");
1377 : 878 : return;
1378 : : }
1379 : : /* Watch for case we reached an POD type and anticipate placement
1380 : : new. */
1381 : 101026 : if (!context.maybe_derived_type)
1382 : : {
1383 : 545 : type = context.outer_type;
1384 : 545 : offset = context.offset;
1385 : : }
1386 : : }
1387 : 117093 : if (tci->type_maybe_changed
1388 : 117093 : && (!types_same_for_odr (type, tci->known_current_type)
1389 : 21 : || offset != tci->known_current_offset))
1390 : 2 : tci->multiple_types_encountered = true;
1391 : 117093 : tci->known_current_type = TYPE_MAIN_VARIANT (type);
1392 : 117093 : tci->known_current_offset = offset;
1393 : 117093 : 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 : 14401690 : csftc_abort_walking_p (unsigned speculative)
1404 : : {
1405 : 14401690 : unsigned max = param_max_speculative_devirt_maydefs;
1406 : 14401690 : 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 : 21251966 : check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
1417 : : {
1418 : 21251966 : gimple *stmt = SSA_NAME_DEF_STMT (vdef);
1419 : 21251966 : struct type_change_info *tci = (struct type_change_info *) data;
1420 : 21251966 : tree fn;
1421 : :
1422 : : /* If we already gave up, just terminate the rest of walk. */
1423 : 21251966 : if (tci->multiple_types_encountered)
1424 : : return true;
1425 : :
1426 : 21251966 : if (is_gimple_call (stmt))
1427 : : {
1428 : 14510273 : if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
1429 : : return false;
1430 : :
1431 : : /* Check for a constructor call. */
1432 : 14506761 : if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
1433 : 13146304 : && DECL_CXX_CONSTRUCTOR_P (fn)
1434 : 755217 : && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
1435 : 15261978 : && gimple_call_num_args (stmt))
1436 : : {
1437 : 755217 : tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
1438 : 755217 : tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
1439 : 755217 : HOST_WIDE_INT offset = 0;
1440 : 755217 : bool reverse;
1441 : :
1442 : 755217 : 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 : 755217 : if (TREE_CODE (op) == ADDR_EXPR)
1450 : : {
1451 : 735613 : HOST_WIDE_INT size;
1452 : 735613 : op = get_ref_base_and_extent_hwi (TREE_OPERAND (op, 0),
1453 : : &offset, &size, &reverse);
1454 : 735613 : if (!op)
1455 : : {
1456 : 0 : tci->speculative++;
1457 : 0 : return csftc_abort_walking_p (tci->speculative);
1458 : : }
1459 : 735613 : if (TREE_CODE (op) == MEM_REF)
1460 : : {
1461 : 52309 : 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 : 52309 : offset += tree_to_shwi (TREE_OPERAND (op, 1))
1467 : 52309 : * BITS_PER_UNIT;
1468 : 52309 : op = TREE_OPERAND (op, 0);
1469 : : }
1470 : 683304 : else if (DECL_P (op))
1471 : : ;
1472 : : else
1473 : : {
1474 : 0 : tci->speculative++;
1475 : 0 : return csftc_abort_walking_p (tci->speculative);
1476 : : }
1477 : 735613 : op = walk_ssa_copies (op);
1478 : : }
1479 : 755217 : if (operand_equal_p (op, tci->instance, 0)
1480 : 156755 : && TYPE_SIZE (type)
1481 : 156755 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
1482 : 156755 : && tree_fits_shwi_p (TYPE_SIZE (type))
1483 : 156755 : && 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 : 880086 : && (tci->offset == offset || contains_polymorphic_type_p (type)))
1498 : : {
1499 : 105071 : record_known_type (tci, type, tci->offset - offset);
1500 : 105071 : 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 : 14401690 : if (dump_file)
1506 : : {
1507 : 724 : fprintf (dump_file, " Function call may change dynamic type:");
1508 : 724 : print_gimple_stmt (dump_file, stmt, 0);
1509 : : }
1510 : 14401690 : tci->speculative++;
1511 : 14401690 : return csftc_abort_walking_p (tci->speculative);
1512 : : }
1513 : : /* Check for inlined virtual table store. */
1514 : 6741693 : else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
1515 : : {
1516 : 51307 : tree type;
1517 : 51307 : HOST_WIDE_INT offset = 0;
1518 : 51307 : if (dump_file)
1519 : : {
1520 : 38 : fprintf (dump_file, " Checking vtbl store: ");
1521 : 38 : print_gimple_stmt (dump_file, stmt, 0);
1522 : : }
1523 : :
1524 : 51307 : type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
1525 : 51307 : if (type == error_mark_node)
1526 : : return false;
1527 : 51272 : gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
1528 : 51272 : if (!type)
1529 : : {
1530 : 38372 : if (dump_file)
1531 : 17 : fprintf (dump_file, " Unanalyzed store may change type.\n");
1532 : 38372 : tci->seen_unanalyzed_store = true;
1533 : 38372 : tci->speculative++;
1534 : : }
1535 : : else
1536 : 12900 : record_known_type (tci, type, offset);
1537 : 51272 : 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 : 3110065 : 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 : 3110065 : struct type_change_info tci;
1573 : 3110065 : ao_ref ao;
1574 : 3110065 : bool function_entry_reached = false;
1575 : 3110065 : tree instance_ref = NULL;
1576 : 3110065 : 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 : 3110065 : HOST_WIDE_INT instance_offset = offset;
1580 : 3110065 : tree instance_outer_type = outer_type;
1581 : :
1582 : 3110065 : if (!instance)
1583 : : return false;
1584 : :
1585 : 3110060 : if (otr_type)
1586 : 200743 : 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 : 3110060 : if (outer_type && otr_type)
1592 : : {
1593 : 178364 : if (!restrict_to_inner_class (otr_type))
1594 : : return false;
1595 : : }
1596 : :
1597 : 3110060 : 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 : 3080280 : 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 : 3080280 : if (gimple_code (call) == GIMPLE_CALL)
1621 : : {
1622 : 3080280 : tree ref = gimple_call_fn (call);
1623 : 3080280 : bool reverse;
1624 : :
1625 : 3080280 : if (TREE_CODE (ref) == OBJ_TYPE_REF)
1626 : : {
1627 : 236585 : ref = OBJ_TYPE_REF_EXPR (ref);
1628 : 236585 : ref = walk_ssa_copies (ref);
1629 : :
1630 : : /* If call target is already known, no need to do the expensive
1631 : : memory walk. */
1632 : 236585 : if (is_gimple_min_invariant (ref))
1633 : 0 : return false;
1634 : :
1635 : : /* Check if definition looks like vtable lookup. */
1636 : 236585 : if (TREE_CODE (ref) == SSA_NAME
1637 : 236585 : && !SSA_NAME_IS_DEFAULT_DEF (ref)
1638 : 236585 : && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))
1639 : 473094 : && TREE_CODE (gimple_assign_rhs1
1640 : : (SSA_NAME_DEF_STMT (ref))) == MEM_REF)
1641 : : {
1642 : 236489 : ref = get_base_address
1643 : 236489 : (TREE_OPERAND (gimple_assign_rhs1
1644 : : (SSA_NAME_DEF_STMT (ref)), 0));
1645 : 236489 : ref = walk_ssa_copies (ref);
1646 : : /* Find base address of the lookup and see if it looks like
1647 : : vptr load. */
1648 : 236489 : if (TREE_CODE (ref) == SSA_NAME
1649 : 236349 : && !SSA_NAME_IS_DEFAULT_DEF (ref)
1650 : 472838 : && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
1651 : : {
1652 : 235823 : HOST_WIDE_INT offset2, size;
1653 : 235823 : tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
1654 : 235823 : tree base_ref
1655 : 235823 : = 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 : 235823 : if (base_ref
1661 : 235823 : && ((TREE_CODE (base_ref) == MEM_REF
1662 : 232578 : && ((offset2 == instance_offset
1663 : 230548 : && TREE_OPERAND (base_ref, 0) == instance)
1664 : 15614 : || (!offset2
1665 : 15614 : && TREE_OPERAND (base_ref, 0)
1666 : : == otr_object)))
1667 : 17108 : || (DECL_P (instance) && base_ref == instance
1668 : 3085 : && offset2 == instance_offset)))
1669 : : {
1670 : 221800 : stmt = SSA_NAME_DEF_STMT (ref);
1671 : 221800 : 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 : 3080280 : if (!instance_ref)
1680 : : {
1681 : : /* If the statement in question does not use memory, we can't tell
1682 : : anything. */
1683 : 8615720 : if (!gimple_vuse (stmt))
1684 : : return false;
1685 : 2850064 : ao_ref_init_from_ptr_and_size (&ao, otr_object, NULL);
1686 : : }
1687 : : else
1688 : : /* Otherwise use the real reference. */
1689 : 221800 : ao_ref_init (&ao, instance_ref);
1690 : :
1691 : : /* We look for vtbl pointer read. */
1692 : 3305010 : ao.size = POINTER_SIZE;
1693 : 3071864 : 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 : 3071864 : if (otr_type)
1699 : : {
1700 : 200047 : ao.base_alias_set
1701 : 377715 : = get_alias_set (outer_type ? outer_type : otr_type);
1702 : 200047 : ao.ref_alias_set
1703 : 200047 : = get_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type))));
1704 : : }
1705 : :
1706 : 3071864 : if (dump_file)
1707 : : {
1708 : 607 : fprintf (dump_file, "Determining dynamic type for call: ");
1709 : 607 : print_gimple_stmt (dump_file, call, 0);
1710 : 607 : fprintf (dump_file, " Starting walk at: ");
1711 : 607 : print_gimple_stmt (dump_file, stmt, 0);
1712 : 607 : fprintf (dump_file, " instance pointer: ");
1713 : 607 : print_generic_expr (dump_file, otr_object, TDF_SLIM);
1714 : 607 : fprintf (dump_file, " Outer instance pointer: ");
1715 : 607 : print_generic_expr (dump_file, instance, TDF_SLIM);
1716 : 607 : fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
1717 : 607 : fprintf (dump_file, " vtbl reference: ");
1718 : 607 : print_generic_expr (dump_file, instance_ref, TDF_SLIM);
1719 : 607 : fprintf (dump_file, "\n");
1720 : : }
1721 : :
1722 : 3071864 : tci.offset = instance_offset;
1723 : 3071864 : tci.instance = instance;
1724 : 3071864 : tci.vtbl_ptr_ref = instance_ref;
1725 : 3071864 : tci.known_current_type = NULL_TREE;
1726 : 3071864 : tci.known_current_offset = 0;
1727 : 3071864 : tci.otr_type = otr_type;
1728 : 3071864 : tci.type_maybe_changed = false;
1729 : 3071864 : tci.multiple_types_encountered = false;
1730 : 3071864 : tci.speculative = 0;
1731 : 3071864 : tci.seen_unanalyzed_store = false;
1732 : :
1733 : 3071864 : unsigned aa_walk_budget = 0;
1734 : 3071864 : if (aa_walk_budget_p)
1735 : 2896301 : aa_walk_budget = *aa_walk_budget_p + 1;
1736 : :
1737 : 3071864 : int walked
1738 : 3071864 : = 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 : 3071864 : if (walked < 0)
1788 : : {
1789 : 91951 : if (dump_file)
1790 : 0 : fprintf (dump_file, " AA walk budget exhausted.\n");
1791 : 91951 : *aa_walk_budget_p = 0;
1792 : 91951 : return false;
1793 : : }
1794 : 2979913 : else if (aa_walk_budget_p)
1795 : 2804350 : *aa_walk_budget_p -= walked;
1796 : :
1797 : 2979913 : if (!tci.type_maybe_changed
1798 : 2979913 : || (outer_type
1799 : 20642 : && !dynamic
1800 : 2555 : && !tci.seen_unanalyzed_store
1801 : 2555 : && !tci.multiple_types_encountered
1802 : 2555 : && ((offset == tci.offset
1803 : 2371 : && types_same_for_odr (tci.known_current_type,
1804 : : outer_type))
1805 : 425 : || (instance_offset == offset
1806 : 241 : && types_same_for_odr (tci.known_current_type,
1807 : : instance_outer_type)))))
1808 : : {
1809 : 2864977 : if (!outer_type || tci.seen_unanalyzed_store)
1810 : : return false;
1811 : 202889 : if (maybe_in_construction)
1812 : 141528 : maybe_in_construction = false;
1813 : 202889 : if (dump_file)
1814 : 225 : fprintf (dump_file, " No dynamic type change found.\n");
1815 : 202889 : return true;
1816 : : }
1817 : :
1818 : 114936 : if (tci.known_current_type
1819 : 114936 : && !function_entry_reached
1820 : 111290 : && !tci.multiple_types_encountered)
1821 : : {
1822 : 111288 : if (!tci.speculative)
1823 : : {
1824 : 36111 : outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
1825 : 36111 : offset = tci.known_current_offset;
1826 : 36111 : dynamic = true;
1827 : 36111 : maybe_in_construction = false;
1828 : 36111 : maybe_derived_type = false;
1829 : 36111 : if (dump_file)
1830 : 28 : fprintf (dump_file, " Determined dynamic type.\n");
1831 : : }
1832 : 75177 : else if (!speculative_outer_type
1833 : 5208 : || speculative_maybe_derived_type)
1834 : : {
1835 : 75177 : speculative_outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
1836 : 75177 : speculative_offset = tci.known_current_offset;
1837 : 75177 : speculative_maybe_derived_type = false;
1838 : 75177 : if (dump_file)
1839 : 8 : fprintf (dump_file, " Determined speculative dynamic type.\n");
1840 : : }
1841 : : }
1842 : 3648 : 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 : 4147474 : 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 : 4147474 : if (!flag_devirtualize_speculatively)
1862 : : return false;
1863 : :
1864 : : /* Non-polymorphic types are useless for deriving likely polymorphic
1865 : : call targets. */
1866 : 4139405 : if (!spec_outer_type || !contains_polymorphic_type_p (spec_outer_type))
1867 : 3120332 : return false;
1868 : :
1869 : : /* If we know nothing, speculation is always good. */
1870 : 1019073 : 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 : 754894 : 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 : 738787 : if (types_must_be_same_for_odr (spec_outer_type, outer_type))
1882 : 1043773 : return maybe_derived_type && !spec_maybe_derived_type;
1883 : :
1884 : : /* If speculation does not contain the type in question, ignore it. */
1885 : 216819 : if (otr_type
1886 : 216819 : && !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 : 215898 : 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 : 57 : if ((!in_lto_p || odr_type_p (outer_type))
1901 : 431552 : && !contains_type_p (spec_outer_type,
1902 : 215776 : spec_offset - offset,
1903 : 215776 : 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 : 4079877 : 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 : 4079877 : if (!new_outer_type)
1918 : : return false;
1919 : :
1920 : : /* restrict_to_inner_class may eliminate wrong speculation making our job
1921 : : easier. */
1922 : 4015657 : if (otr_type)
1923 : 2561 : restrict_to_inner_class (otr_type);
1924 : :
1925 : 4015657 : 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 : 313532 : if (!speculative_outer_type
1932 : 89016 : || (speculative_maybe_derived_type
1933 : 88321 : && !new_maybe_derived_type))
1934 : : {
1935 : 229037 : speculative_outer_type = new_outer_type;
1936 : 229037 : speculative_offset = new_offset;
1937 : 229037 : speculative_maybe_derived_type = new_maybe_derived_type;
1938 : 229037 : return true;
1939 : : }
1940 : 84495 : else if (types_must_be_same_for_odr (speculative_outer_type,
1941 : : new_outer_type))
1942 : : {
1943 : 62039 : 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 : 62035 : 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 : 22456 : else if (speculative_outer_type
1971 : 22456 : && speculative_maybe_derived_type
1972 : 44476 : && (new_offset > speculative_offset
1973 : 21444 : || (new_offset == speculative_offset
1974 : 21401 : && contains_type_p (new_outer_type,
1975 : : 0, speculative_outer_type, false))))
1976 : : {
1977 : 1012 : tree old_outer_type = speculative_outer_type;
1978 : 1012 : HOST_WIDE_INT old_offset = speculative_offset;
1979 : 1012 : bool old_maybe_derived_type = speculative_maybe_derived_type;
1980 : :
1981 : 1012 : speculative_outer_type = new_outer_type;
1982 : 1012 : speculative_offset = new_offset;
1983 : 1012 : speculative_maybe_derived_type = new_maybe_derived_type;
1984 : :
1985 : 1012 : 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 : 1012 : 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 : 1012 : return (old_offset != speculative_offset
1998 : 436 : || old_maybe_derived_type != speculative_maybe_derived_type
1999 : 1448 : || 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 : 36 : 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 : 36 : if (!new_outer_type && speculative_outer_type)
2015 : : {
2016 : 19 : clear_speculation ();
2017 : 19 : return true;
2018 : : }
2019 : :
2020 : : /* restrict_to_inner_class may eliminate wrong speculation making our job
2021 : : easier. */
2022 : 17 : if (otr_type)
2023 : 0 : restrict_to_inner_class (otr_type);
2024 : :
2025 : 17 : if (!speculative_outer_type
2026 : 19 : || !speculation_consistent_p (speculative_outer_type,
2027 : : speculative_offset,
2028 : 2 : speculative_maybe_derived_type,
2029 : : otr_type))
2030 : 16 : return false;
2031 : :
2032 : 1 : 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 : 1 : else if (types_must_be_same_for_odr (speculative_outer_type,
2040 : : new_outer_type))
2041 : : {
2042 : 1 : if (speculative_offset != new_offset)
2043 : : {
2044 : 0 : clear_speculation ();
2045 : 0 : return true;
2046 : : }
2047 : : else
2048 : : {
2049 : 1 : 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 : 0 : else if (contains_type_p (new_outer_type, new_offset - speculative_offset,
2060 : : speculative_outer_type, false, false))
2061 : : return false;
2062 : 0 : else if (contains_type_p (speculative_outer_type,
2063 : 0 : 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 : 0 : else if (contains_type_p (new_outer_type,
2073 : 0 : new_offset - speculative_offset,
2074 : : speculative_outer_type, false, true))
2075 : : {
2076 : 0 : 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 : 0 : else if (contains_type_p (speculative_outer_type,
2085 : 0 : 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 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
2095 : 0 : fprintf (dump_file, "Giving up on speculative meet\n");
2096 : 0 : clear_speculation ();
2097 : 0 : 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 : 115071 : ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
2108 : : tree otr_type)
2109 : : {
2110 : 115071 : bool updated = false;
2111 : :
2112 : 161674 : 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 : 114340 : if (otr_type && !invalid && !ctx.invalid)
2118 : : {
2119 : 26905 : restrict_to_inner_class (otr_type);
2120 : 26905 : ctx.restrict_to_inner_class (otr_type);
2121 : 26905 : if(invalid)
2122 : : return false;
2123 : : }
2124 : :
2125 : 114289 : if (dump_file && (dump_flags & TDF_DETAILS))
2126 : : {
2127 : 92 : fprintf (dump_file, "Polymorphic call context combine:");
2128 : 92 : dump (dump_file);
2129 : 92 : fprintf (dump_file, "With context: ");
2130 : 92 : ctx.dump (dump_file);
2131 : 92 : if (otr_type)
2132 : : {
2133 : 35 : fprintf (dump_file, "To be used with type: ");
2134 : 35 : print_generic_expr (dump_file, otr_type, TDF_SLIM);
2135 : 35 : fprintf (dump_file, "\n");
2136 : : }
2137 : : }
2138 : :
2139 : : /* If call is known to be invalid, we are done. */
2140 : 114289 : 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 : 114289 : if (!ctx.outer_type)
2148 : : ;
2149 : 68601 : else if (!outer_type)
2150 : : {
2151 : 14157 : outer_type = ctx.outer_type;
2152 : 14157 : offset = ctx.offset;
2153 : 14157 : dynamic = ctx.dynamic;
2154 : 14157 : maybe_in_construction = ctx.maybe_in_construction;
2155 : 14157 : maybe_derived_type = ctx.maybe_derived_type;
2156 : 14157 : updated = true;
2157 : : }
2158 : : /* If types are known to be same, merging is quite easy. */
2159 : 54444 : else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
2160 : : {
2161 : 36017 : if (offset != ctx.offset
2162 : 4 : && TYPE_SIZE (outer_type)
2163 : 36021 : && 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 : 36013 : if (dump_file && (dump_flags & TDF_DETAILS))
2173 : 30 : fprintf (dump_file, "Outer types match, merging flags\n");
2174 : 36013 : if (maybe_in_construction && !ctx.maybe_in_construction)
2175 : : {
2176 : 11046 : updated = true;
2177 : 11046 : maybe_in_construction = false;
2178 : : }
2179 : 36013 : if (maybe_derived_type && !ctx.maybe_derived_type)
2180 : : {
2181 : 1982 : updated = true;
2182 : 1982 : maybe_derived_type = false;
2183 : : }
2184 : 36013 : if (dynamic && !ctx.dynamic)
2185 : : {
2186 : 11385 : updated = true;
2187 : 11385 : dynamic = false;
2188 : : }
2189 : : }
2190 : : /* If we know the type precisely, there is not much to improve. */
2191 : 18427 : else if (!maybe_derived_type && !maybe_in_construction
2192 : 13725 : && !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 : 427 : 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 : 18000 : else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
2213 : : outer_type, false, false))
2214 : : {
2215 : 1948 : if (dump_file && (dump_flags & TDF_DETAILS))
2216 : 0 : fprintf (dump_file, "Second type contain the first as a field\n");
2217 : :
2218 : 1948 : if (maybe_derived_type)
2219 : : {
2220 : 1380 : outer_type = ctx.outer_type;
2221 : 1380 : maybe_derived_type = ctx.maybe_derived_type;
2222 : 1380 : offset = ctx.offset;
2223 : 1380 : dynamic = ctx.dynamic;
2224 : 1380 : 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 : 1948 : 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 : 16052 : else if (contains_type_p (outer_type, offset - ctx.offset,
2239 : : ctx.outer_type, false, false))
2240 : : {
2241 : 43 : if (dump_file && (dump_flags & TDF_DETAILS))
2242 : 0 : fprintf (dump_file, "First type contain the second as a field\n");
2243 : :
2244 : 43 : 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 : 16009 : else if (contains_type_p (ctx.outer_type,
2253 : 16009 : ctx.offset - offset, outer_type, false, true))
2254 : : {
2255 : 7736 : if (dump_file && (dump_flags & TDF_DETAILS))
2256 : 12 : fprintf (dump_file, "First type is base of second\n");
2257 : 7736 : if (!maybe_derived_type)
2258 : : {
2259 : 4896 : if (!ctx.maybe_in_construction
2260 : 4896 : && 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 : 2840 : outer_type = ctx.outer_type;
2271 : 2840 : maybe_in_construction = ctx.maybe_in_construction;
2272 : 2840 : maybe_derived_type = ctx.maybe_derived_type;
2273 : 2840 : offset = ctx.offset;
2274 : 2840 : dynamic = ctx.dynamic;
2275 : 2840 : updated = true;
2276 : : }
2277 : : }
2278 : : /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
2279 : 8273 : else if (contains_type_p (outer_type,
2280 : 8273 : offset - ctx.offset, ctx.outer_type, false, true))
2281 : : {
2282 : 8167 : if (dump_file && (dump_flags & TDF_DETAILS))
2283 : 26 : fprintf (dump_file, "Second type is base of first\n");
2284 : 8167 : if (!ctx.maybe_derived_type)
2285 : : {
2286 : 115 : if (!maybe_in_construction
2287 : 115 : && 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 : 115 : else if (maybe_in_construction)
2295 : : {
2296 : 115 : outer_type = ctx.outer_type;
2297 : 115 : maybe_in_construction = ctx.maybe_in_construction;
2298 : 115 : maybe_derived_type = ctx.maybe_derived_type;
2299 : 115 : offset = ctx.offset;
2300 : 115 : dynamic = ctx.dynamic;
2301 : 115 : updated = true;
2302 : : }
2303 : : }
2304 : : }
2305 : : /* TODO handle merging using hierarchy. */
2306 : 106 : else if (dump_file && (dump_flags & TDF_DETAILS))
2307 : 3 : fprintf (dump_file, "Giving up on merge\n");
2308 : :
2309 : 228570 : updated |= combine_speculation_with (ctx.speculative_outer_type,
2310 : : ctx.speculative_offset,
2311 : 114285 : ctx.speculative_maybe_derived_type,
2312 : : otr_type);
2313 : :
2314 : 114285 : if (updated && dump_file && (dump_flags & TDF_DETAILS))
2315 : : {
2316 : 48 : fprintf (dump_file, "Updated as: ");
2317 : 48 : dump (dump_file);
2318 : 48 : 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 : 85418 : ipa_polymorphic_call_context::make_speculative (tree otr_type)
2338 : : {
2339 : 85418 : tree spec_outer_type = outer_type;
2340 : 85418 : HOST_WIDE_INT spec_offset = offset;
2341 : 85418 : bool spec_maybe_derived_type = maybe_derived_type;
2342 : :
2343 : 85418 : if (invalid)
2344 : : {
2345 : 0 : invalid = false;
2346 : 0 : clear_outer_type ();
2347 : 0 : clear_speculation ();
2348 : 0 : return;
2349 : : }
2350 : 85418 : if (!outer_type)
2351 : : return;
2352 : 21494 : clear_outer_type ();
2353 : 21494 : 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 : 109740 : ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
2363 : : tree otr_type)
2364 : : {
2365 : 109740 : if (dynamic)
2366 : 85418 : make_speculative (otr_type);
2367 : 24322 : else if (in_poly_cdtor)
2368 : 15761 : maybe_in_construction = true;
2369 : 109740 : }
2370 : :
2371 : : /* Return TRUE if this context conveys the same information as OTHER. */
2372 : :
2373 : : bool
2374 : 63008 : ipa_polymorphic_call_context::equal_to
2375 : : (const ipa_polymorphic_call_context &x) const
2376 : : {
2377 : 63008 : if (useless_p ())
2378 : 159 : return x.useless_p ();
2379 : 62849 : if (invalid)
2380 : 0 : return x.invalid;
2381 : 114143 : if (x.useless_p () || x.invalid)
2382 : : return false;
2383 : :
2384 : 62846 : if (outer_type)
2385 : : {
2386 : 12762 : if (!x.outer_type
2387 : 12620 : || !types_odr_comparable (outer_type, x.outer_type)
2388 : 12620 : || !types_same_for_odr (outer_type, x.outer_type)
2389 : 12394 : || offset != x.offset
2390 : 12373 : || maybe_in_construction != x.maybe_in_construction
2391 : 12362 : || maybe_derived_type != x.maybe_derived_type
2392 : 25077 : || dynamic != x.dynamic)
2393 : 532 : return false;
2394 : : }
2395 : 50084 : else if (x.outer_type)
2396 : : return false;
2397 : :
2398 : :
2399 : 61954 : if (speculative_outer_type
2400 : 112833 : && speculation_consistent_p (speculative_outer_type, speculative_offset,
2401 : 50879 : speculative_maybe_derived_type, NULL_TREE))
2402 : : {
2403 : 49191 : if (!x.speculative_outer_type)
2404 : : return false;
2405 : :
2406 : 49191 : if (!types_odr_comparable (speculative_outer_type,
2407 : : x.speculative_outer_type)
2408 : 49191 : || !types_same_for_odr (speculative_outer_type,
2409 : 49191 : x.speculative_outer_type)
2410 : 48893 : || speculative_offset != x.speculative_offset
2411 : 98020 : || speculative_maybe_derived_type != x.speculative_maybe_derived_type)
2412 : 365 : return false;
2413 : : }
2414 : 12763 : else if (x.speculative_outer_type
2415 : 14351 : && x.speculation_consistent_p (x.speculative_outer_type,
2416 : 1588 : x.speculative_offset,
2417 : 1588 : x.speculative_maybe_derived_type,
2418 : : NULL))
2419 : : return false;
2420 : :
2421 : : return true;
2422 : : }
2423 : :
2424 : : /* Modify context to be strictly less restrictive than CTX. */
2425 : :
2426 : : bool
2427 : 70 : ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx,
2428 : : tree otr_type)
2429 : : {
2430 : 70 : bool updated = false;
2431 : :
2432 : 130 : if (useless_p () || ctx.invalid)
2433 : : return false;
2434 : :
2435 : : /* Restricting context to inner type makes merging easier, however do not
2436 : : do that unless we know how the context is used (OTR_TYPE is non-NULL) */
2437 : 70 : if (otr_type && !useless_p () && !ctx.useless_p ())
2438 : : {
2439 : 0 : restrict_to_inner_class (otr_type);
2440 : 0 : ctx.restrict_to_inner_class (otr_type);
2441 : 0 : if(invalid)
2442 : : return false;
2443 : : }
2444 : :
2445 : 70 : if (equal_to (ctx))
2446 : : return false;
2447 : :
2448 : 39 : if (ctx.useless_p () || invalid)
2449 : : {
2450 : 3 : *this = ctx;
2451 : 3 : return true;
2452 : : }
2453 : :
2454 : 36 : if (dump_file && (dump_flags & TDF_DETAILS))
2455 : : {
2456 : 0 : fprintf (dump_file, "Polymorphic call context meet:");
2457 : 0 : dump (dump_file);
2458 : 0 : fprintf (dump_file, "With context: ");
2459 : 0 : ctx.dump (dump_file);
2460 : 0 : if (otr_type)
2461 : : {
2462 : 0 : fprintf (dump_file, "To be used with type: ");
2463 : 0 : print_generic_expr (dump_file, otr_type, TDF_SLIM);
2464 : 0 : fprintf (dump_file, "\n");
2465 : : }
2466 : : }
2467 : :
2468 : 36 : if (!dynamic && ctx.dynamic)
2469 : : {
2470 : 6 : dynamic = true;
2471 : 6 : updated = true;
2472 : : }
2473 : :
2474 : : /* If call is known to be invalid, we are done. */
2475 : 36 : if (!outer_type)
2476 : : ;
2477 : 16 : else if (!ctx.outer_type)
2478 : : {
2479 : 0 : clear_outer_type ();
2480 : 0 : updated = true;
2481 : : }
2482 : : /* If types are known to be same, merging is quite easy. */
2483 : 16 : else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
2484 : : {
2485 : 13 : if (offset != ctx.offset
2486 : 0 : && TYPE_SIZE (outer_type)
2487 : 13 : && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
2488 : : {
2489 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
2490 : 0 : fprintf (dump_file, "Outer types match, offset mismatch -> clearing\n");
2491 : 0 : clear_outer_type ();
2492 : 0 : return true;
2493 : : }
2494 : 13 : if (dump_file && (dump_flags & TDF_DETAILS))
2495 : 0 : fprintf (dump_file, "Outer types match, merging flags\n");
2496 : 13 : if (!maybe_in_construction && ctx.maybe_in_construction)
2497 : : {
2498 : 0 : updated = true;
2499 : 0 : maybe_in_construction = true;
2500 : : }
2501 : 13 : if (!maybe_derived_type && ctx.maybe_derived_type)
2502 : : {
2503 : 6 : updated = true;
2504 : 6 : maybe_derived_type = true;
2505 : : }
2506 : 13 : if (!dynamic && ctx.dynamic)
2507 : : {
2508 : 0 : updated = true;
2509 : 0 : dynamic = true;
2510 : : }
2511 : : }
2512 : : /* See if one type contains the other as a field (not base). */
2513 : 3 : else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
2514 : : outer_type, false, false))
2515 : : {
2516 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
2517 : 0 : fprintf (dump_file, "Second type contain the first as a field\n");
2518 : :
2519 : : /* The second type is more specified, so we keep the first.
2520 : : We need to set DYNAMIC flag to avoid declaring context INVALID
2521 : : of OFFSET ends up being out of range. */
2522 : 0 : if (!dynamic
2523 : 0 : && (ctx.dynamic
2524 : 0 : || (!otr_type
2525 : 0 : && (!TYPE_SIZE (ctx.outer_type)
2526 : 0 : || !TYPE_SIZE (outer_type)
2527 : 0 : || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
2528 : 0 : TYPE_SIZE (outer_type), 0)))))
2529 : : {
2530 : 0 : dynamic = true;
2531 : 0 : updated = true;
2532 : : }
2533 : : }
2534 : 3 : else if (contains_type_p (outer_type, offset - ctx.offset,
2535 : : ctx.outer_type, false, false))
2536 : : {
2537 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
2538 : 0 : fprintf (dump_file, "First type contain the second as a field\n");
2539 : :
2540 : 0 : if (!dynamic
2541 : 0 : && (ctx.dynamic
2542 : 0 : || (!otr_type
2543 : 0 : && (!TYPE_SIZE (ctx.outer_type)
2544 : 0 : || !TYPE_SIZE (outer_type)
2545 : 0 : || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
2546 : 0 : TYPE_SIZE (outer_type), 0)))))
2547 : : dynamic = true;
2548 : 0 : outer_type = ctx.outer_type;
2549 : 0 : offset = ctx.offset;
2550 : 0 : dynamic = ctx.dynamic;
2551 : 0 : maybe_in_construction = ctx.maybe_in_construction;
2552 : 0 : maybe_derived_type = ctx.maybe_derived_type;
2553 : 0 : updated = true;
2554 : : }
2555 : : /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
2556 : 3 : else if (contains_type_p (ctx.outer_type,
2557 : 3 : ctx.offset - offset, outer_type, false, true))
2558 : : {
2559 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
2560 : 0 : fprintf (dump_file, "First type is base of second\n");
2561 : 0 : if (!maybe_derived_type)
2562 : : {
2563 : 0 : maybe_derived_type = true;
2564 : 0 : updated = true;
2565 : : }
2566 : 0 : if (!maybe_in_construction && ctx.maybe_in_construction)
2567 : : {
2568 : 0 : maybe_in_construction = true;
2569 : 0 : updated = true;
2570 : : }
2571 : 0 : if (!dynamic && ctx.dynamic)
2572 : : {
2573 : 0 : dynamic = true;
2574 : 0 : updated = true;
2575 : : }
2576 : : }
2577 : : /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
2578 : 3 : else if (contains_type_p (outer_type,
2579 : 3 : offset - ctx.offset, ctx.outer_type, false, true))
2580 : : {
2581 : 3 : if (dump_file && (dump_flags & TDF_DETAILS))
2582 : 0 : fprintf (dump_file, "Second type is base of first\n");
2583 : 3 : outer_type = ctx.outer_type;
2584 : 3 : offset = ctx.offset;
2585 : 3 : updated = true;
2586 : 3 : if (!maybe_derived_type)
2587 : 3 : maybe_derived_type = true;
2588 : 3 : if (!maybe_in_construction && ctx.maybe_in_construction)
2589 : 0 : maybe_in_construction = true;
2590 : 3 : if (!dynamic && ctx.dynamic)
2591 : 0 : dynamic = true;
2592 : : }
2593 : : /* TODO handle merging using hierarchy. */
2594 : : else
2595 : : {
2596 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
2597 : 0 : fprintf (dump_file, "Giving up on meet\n");
2598 : 0 : clear_outer_type ();
2599 : 0 : updated = true;
2600 : : }
2601 : :
2602 : 72 : updated |= meet_speculation_with (ctx.speculative_outer_type,
2603 : : ctx.speculative_offset,
2604 : 36 : ctx.speculative_maybe_derived_type,
2605 : : otr_type);
2606 : :
2607 : 36 : if (updated && dump_file && (dump_flags & TDF_DETAILS))
2608 : : {
2609 : 0 : fprintf (dump_file, "Updated as: ");
2610 : 0 : dump (dump_file);
2611 : 0 : fprintf (dump_file, "\n");
2612 : : }
2613 : : return updated;
2614 : : }
|