Line data Source code
1 : /* Utilities for ipa analysis.
2 : Copyright (C) 2004-2026 Free Software Foundation, Inc.
3 : Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
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 : #ifndef GCC_IPA_UTILS_H
22 : #define GCC_IPA_UTILS_H
23 :
24 : struct ipa_dfs_info {
25 : int dfn_number;
26 : int low_link;
27 : /* This field will have the samy value for any two nodes in the same strongly
28 : connected component. */
29 : int scc_no;
30 : bool new_node;
31 : bool on_stack;
32 : struct cgraph_node* next_cycle;
33 : void *aux;
34 : };
35 :
36 :
37 : /* In ipa-utils.cc */
38 : void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
39 : int ipa_reduced_postorder (struct cgraph_node **, bool,
40 : bool (*ignore_edge) (struct cgraph_edge *));
41 : void ipa_free_postorder_info (void);
42 : vec<cgraph_node *> ipa_get_nodes_in_cycle (struct cgraph_node *);
43 : bool ipa_edge_within_scc (struct cgraph_edge *);
44 : int ipa_reverse_postorder (struct cgraph_node **);
45 : tree get_base_var (tree);
46 : void ipa_merge_profiles (struct cgraph_node *dst,
47 : struct cgraph_node *src, bool preserve_body = false);
48 : bool recursive_call_p (tree, tree);
49 : bool stmt_may_terminate_function_p (function *fun, gimple *stmt, bool assume_return_or_eh);
50 : bitmap find_always_executed_bbs (function *fun, bool assume_return_or_eh);
51 :
52 : /* In ipa-pure-const.cc */
53 : bool finite_function_p ();
54 : bool builtin_safe_for_const_function_p (bool *, tree);
55 : bool ipa_make_function_const (cgraph_node *, bool, bool);
56 : bool ipa_make_function_pure (cgraph_node *, bool, bool);
57 :
58 : /* In ipa-profile.cc */
59 : bool ipa_propagate_frequency (struct cgraph_node *node);
60 : void ipa_profile_cc_finalize (void);
61 :
62 : /* In ipa-icf.cc */
63 : void ipa_icf_cc_finalize (void);
64 :
65 : /* In ipa-sra.cc */
66 : void ipa_sra_cc_finalize (void);
67 :
68 : /* In ipa-devirt.cc */
69 :
70 : struct odr_type_d;
71 : typedef odr_type_d *odr_type;
72 : extern bool thunk_expansion;
73 : void build_type_inheritance_graph (void);
74 : void rebuild_type_inheritance_graph (void);
75 : void update_type_inheritance_graph (void);
76 : vec <cgraph_node *>
77 : possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
78 : ipa_polymorphic_call_context,
79 : bool *copletep = NULL,
80 : void **cache_token = NULL,
81 : bool speuclative = false);
82 : odr_type get_odr_type (tree, bool insert = false);
83 : bool odr_type_p (const_tree);
84 : bool possible_polymorphic_call_target_p (tree ref, gimple *stmt, struct cgraph_node *n);
85 : void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
86 : const ipa_polymorphic_call_context &,
87 : bool verbose = true);
88 : bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
89 : const ipa_polymorphic_call_context &,
90 : struct cgraph_node *);
91 : tree polymorphic_ctor_dtor_p (tree, bool);
92 : tree inlined_polymorphic_ctor_dtor_block_p (tree, bool);
93 : bool decl_maybe_in_construction_p (tree, tree, gimple *, tree);
94 : tree vtable_pointer_value_to_binfo (const_tree);
95 : bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
96 : tree subbinfo_with_vtable_at_offset (tree, unsigned HOST_WIDE_INT, tree);
97 : void compare_virtual_tables (varpool_node *, varpool_node *);
98 : bool type_all_derivations_known_p (const_tree);
99 : bool type_known_to_have_no_derivations_p (tree);
100 : bool contains_polymorphic_type_p (const_tree);
101 : void register_odr_type (tree);
102 : bool types_must_be_same_for_odr (tree, tree);
103 : bool types_odr_comparable (tree, tree);
104 : cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT,
105 : ipa_polymorphic_call_context);
106 : void warn_types_mismatch (tree t1, tree t2, location_t loc1 = UNKNOWN_LOCATION,
107 : location_t loc2 = UNKNOWN_LOCATION);
108 : bool odr_or_derived_type_p (const_tree t);
109 : bool odr_types_equivalent_p (tree type1, tree type2);
110 : bool odr_type_violation_reported_p (tree type);
111 : tree prevailing_odr_type (tree type);
112 : void enable_odr_based_tbaa (tree type);
113 : bool odr_based_tbaa_p (const_tree type);
114 : void set_type_canonical_for_odr_type (tree type, tree canonical);
115 : void warn_function_returns_nonnull (tree);
116 :
117 : void register_odr_enum (tree type);
118 :
119 : /* Return vector containing possible targets of polymorphic call E.
120 : If COMPLETEP is non-NULL, store true if the list is complete.
121 : CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
122 : in the target cache. If user needs to visit every target list
123 : just once, it can memoize them.
124 :
125 : Returned vector is placed into cache. It is NOT caller's responsibility
126 : to free it. The vector can be freed on cgraph_remove_node call if
127 : the particular node is a virtual function present in the cache. */
128 :
129 : inline vec <cgraph_node *>
130 228481 : possible_polymorphic_call_targets (struct cgraph_edge *e,
131 : bool *completep = NULL,
132 : void **cache_token = NULL,
133 : bool speculative = false)
134 : {
135 228481 : ipa_polymorphic_call_context context(e);
136 :
137 228481 : cgraph_polymorphic_indirect_info *pii
138 228481 : = as_a <cgraph_polymorphic_indirect_info *> (e->indirect_info);
139 228481 : gcc_checking_assert (pii->usable_p ());
140 228481 : return possible_polymorphic_call_targets (pii->otr_type,
141 : pii->otr_token,
142 : context,
143 : completep, cache_token,
144 228481 : speculative);
145 : }
146 :
147 : /* Same as above but taking OBJ_TYPE_REF as an parameter. */
148 :
149 : inline vec <cgraph_node *>
150 623166 : possible_polymorphic_call_targets (tree ref,
151 : gimple *call,
152 : bool *completep = NULL,
153 : void **cache_token = NULL)
154 : {
155 623166 : ipa_polymorphic_call_context context (current_function_decl, ref, call);
156 :
157 1246332 : return possible_polymorphic_call_targets (obj_type_ref_class (ref),
158 : tree_to_uhwi
159 623166 : (OBJ_TYPE_REF_TOKEN (ref)),
160 : context,
161 623166 : completep, cache_token);
162 : }
163 :
164 : /* Dump possible targets of a polymorphic call E into F. */
165 :
166 : inline void
167 50 : dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e,
168 : bool verbose = true)
169 : {
170 50 : ipa_polymorphic_call_context context(e);
171 :
172 50 : cgraph_polymorphic_indirect_info *pii
173 50 : = as_a <cgraph_polymorphic_indirect_info *> (e->indirect_info);
174 50 : if (!pii->usable_p ())
175 0 : return;
176 50 : dump_possible_polymorphic_call_targets (f, pii->otr_type,
177 : pii->otr_token,
178 : context, verbose);
179 : }
180 :
181 : /* Return true if N can be possibly target of a polymorphic call of
182 : E. */
183 :
184 : inline bool
185 34040 : possible_polymorphic_call_target_p (struct cgraph_edge *e,
186 : struct cgraph_node *n)
187 : {
188 34040 : ipa_polymorphic_call_context context(e);
189 :
190 34040 : cgraph_polymorphic_indirect_info *pii
191 34040 : = as_a <cgraph_polymorphic_indirect_info *> (e->indirect_info);
192 34040 : if (!pii->usable_p ())
193 : return true;
194 34040 : return possible_polymorphic_call_target_p (pii->otr_type,
195 : pii->otr_token,
196 34040 : context, n);
197 : }
198 :
199 : /* Return true if BINFO corresponds to a type with virtual methods.
200 :
201 : Every type has several BINFOs. One is the BINFO associated by the type
202 : while other represents bases of derived types. The BINFOs representing
203 : bases do not have BINFO_VTABLE pointer set when this is the single
204 : inheritance (because vtables are shared). Look up the BINFO of type
205 : and check presence of its vtable. */
206 :
207 : inline bool
208 13475715 : polymorphic_type_binfo_p (const_tree binfo)
209 : {
210 26951430 : return (BINFO_TYPE (binfo) && TYPE_BINFO (BINFO_TYPE (binfo))
211 26949559 : && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))));
212 : }
213 :
214 : /* Return true if T is a type with linkage defined. */
215 :
216 : inline bool
217 13783724 : type_with_linkage_p (const_tree t)
218 : {
219 13783724 : gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
220 13783724 : if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
221 : return false;
222 :
223 : /* After free_lang_data was run we can recongize
224 : types with linkage by presence of mangled name. */
225 13512192 : if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
226 : return true;
227 :
228 10243738 : if (in_lto_p)
229 : return false;
230 :
231 : /* We used to check for TYPE_STUB_DECL but that is set to NULL for forward
232 : declarations. */
233 :
234 10231387 : if (!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
235 : return false;
236 :
237 : /* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */
238 10145622 : if (!TYPE_CONTEXT (t))
239 2230 : return false;
240 :
241 : return true;
242 : }
243 :
244 : /* Return true if T is in anonymous namespace.
245 : This works only on those C++ types with linkage defined. */
246 :
247 : inline bool
248 7016005 : type_in_anonymous_namespace_p (const_tree t)
249 : {
250 7016005 : gcc_checking_assert (type_with_linkage_p (t));
251 :
252 : /* free_lang_data clears TYPE_STUB_DECL but sets assembler name to
253 : "<anon>" */
254 7016005 : if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
255 3269790 : return !strcmp ("<anon>",
256 1634895 : IDENTIFIER_POINTER
257 1634895 : (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
258 5381110 : else if (!TYPE_STUB_DECL (t))
259 : return false;
260 : else
261 5381110 : return !TREE_PUBLIC (TYPE_STUB_DECL (t));
262 : }
263 :
264 : /* Return true of T is type with One Definition Rule info attached.
265 : It means that either it is anonymous type or it has assembler name
266 : set. */
267 :
268 : inline bool
269 2290753 : odr_type_p (const_tree t)
270 : {
271 : /* We do not have this information when not in LTO, but we do not need
272 : to care, since it is used only for type merging. */
273 2290753 : gcc_checking_assert (in_lto_p || flag_lto || flag_generate_offload);
274 3212046 : return TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
275 3042575 : && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t));
276 : }
277 :
278 : /* If TYPE has mangled ODR name, return it. Otherwise return NULL.
279 : The function works only when free_lang_data is run. */
280 :
281 : inline const char *
282 66 : get_odr_name_for_type (tree type)
283 : {
284 66 : tree type_name = TYPE_NAME (type);
285 66 : if (type_name == NULL_TREE
286 52 : || TREE_CODE (type_name) != TYPE_DECL
287 116 : || !DECL_ASSEMBLER_NAME_SET_P (type_name))
288 : return NULL;
289 :
290 38 : return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (type_name));
291 : }
292 :
293 : /* Return true if we are going to do LTO streaming. */
294 :
295 : inline bool
296 37339167 : lto_streaming_expected_p ()
297 : {
298 : /* Compilation before LTO stremaing. */
299 37339167 : if (flag_lto && !in_lto_p && symtab->state < IPA_SSA_AFTER_INLINING)
300 : return true;
301 : /* WPA or incremental link. */
302 36620959 : return (flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO);
303 : }
304 :
305 : #endif /* GCC_IPA_UTILS_H */
|