Branch data Line data Source code
1 : : /* Utilities for ipa analysis.
2 : : Copyright (C) 2004-2024 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 : 216255 : possible_polymorphic_call_targets (struct cgraph_edge *e,
131 : : bool *completep = NULL,
132 : : void **cache_token = NULL,
133 : : bool speculative = false)
134 : : {
135 : 216255 : ipa_polymorphic_call_context context(e);
136 : :
137 : 216255 : return possible_polymorphic_call_targets (e->indirect_info->otr_type,
138 : 216255 : e->indirect_info->otr_token,
139 : : context,
140 : : completep, cache_token,
141 : 216255 : speculative);
142 : : }
143 : :
144 : : /* Same as above but taking OBJ_TYPE_REF as an parameter. */
145 : :
146 : : inline vec <cgraph_node *>
147 : 500485 : possible_polymorphic_call_targets (tree ref,
148 : : gimple *call,
149 : : bool *completep = NULL,
150 : : void **cache_token = NULL)
151 : : {
152 : 500485 : ipa_polymorphic_call_context context (current_function_decl, ref, call);
153 : :
154 : 1000970 : return possible_polymorphic_call_targets (obj_type_ref_class (ref),
155 : : tree_to_uhwi
156 : 500485 : (OBJ_TYPE_REF_TOKEN (ref)),
157 : : context,
158 : 500485 : completep, cache_token);
159 : : }
160 : :
161 : : /* Dump possible targets of a polymorphic call E into F. */
162 : :
163 : : inline void
164 : 53 : dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e,
165 : : bool verbose = true)
166 : : {
167 : 53 : ipa_polymorphic_call_context context(e);
168 : :
169 : 53 : dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
170 : 53 : e->indirect_info->otr_token,
171 : : context, verbose);
172 : 53 : }
173 : :
174 : : /* Return true if N can be possibly target of a polymorphic call of
175 : : E. */
176 : :
177 : : inline bool
178 : 25749 : possible_polymorphic_call_target_p (struct cgraph_edge *e,
179 : : struct cgraph_node *n)
180 : : {
181 : 25749 : ipa_polymorphic_call_context context(e);
182 : :
183 : 25749 : return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
184 : 25749 : e->indirect_info->otr_token,
185 : 25749 : context, n);
186 : : }
187 : :
188 : : /* Return true if BINFO corresponds to a type with virtual methods.
189 : :
190 : : Every type has several BINFOs. One is the BINFO associated by the type
191 : : while other represents bases of derived types. The BINFOs representing
192 : : bases do not have BINFO_VTABLE pointer set when this is the single
193 : : inheritance (because vtables are shared). Look up the BINFO of type
194 : : and check presence of its vtable. */
195 : :
196 : : inline bool
197 : 11427141 : polymorphic_type_binfo_p (const_tree binfo)
198 : : {
199 : 22854282 : return (BINFO_TYPE (binfo) && TYPE_BINFO (BINFO_TYPE (binfo))
200 : 22852414 : && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))));
201 : : }
202 : :
203 : : /* Return true if T is a type with linkage defined. */
204 : :
205 : : inline bool
206 : 11453549 : type_with_linkage_p (const_tree t)
207 : : {
208 : 11453549 : gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
209 : 11453549 : if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
210 : : return false;
211 : :
212 : : /* After free_lang_data was run we can recongize
213 : : types with linkage by presence of mangled name. */
214 : 11196128 : if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
215 : : return true;
216 : :
217 : 8849813 : if (in_lto_p)
218 : : return false;
219 : :
220 : : /* We used to check for TYPE_STUB_DECL but that is set to NULL for forward
221 : : declarations. */
222 : :
223 : 8838942 : if (!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
224 : : return false;
225 : :
226 : : /* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */
227 : 8602305 : if (!TYPE_CONTEXT (t))
228 : 3711 : return false;
229 : :
230 : : return true;
231 : : }
232 : :
233 : : /* Return true if T is in anonymous namespace.
234 : : This works only on those C++ types with linkage defined. */
235 : :
236 : : inline bool
237 : 5763698 : type_in_anonymous_namespace_p (const_tree t)
238 : : {
239 : 5763698 : gcc_checking_assert (type_with_linkage_p (t));
240 : :
241 : : /* free_lang_data clears TYPE_STUB_DECL but sets assembler name to
242 : : "<anon>" */
243 : 5763698 : if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
244 : 2350768 : return !strcmp ("<anon>",
245 : 1175384 : IDENTIFIER_POINTER
246 : 1175384 : (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
247 : 4588314 : else if (!TYPE_STUB_DECL (t))
248 : : return false;
249 : : else
250 : 4588314 : return !TREE_PUBLIC (TYPE_STUB_DECL (t));
251 : : }
252 : :
253 : : /* Return true of T is type with One Definition Rule info attached.
254 : : It means that either it is anonymous type or it has assembler name
255 : : set. */
256 : :
257 : : inline bool
258 : 2236282 : odr_type_p (const_tree t)
259 : : {
260 : : /* We do not have this information when not in LTO, but we do not need
261 : : to care, since it is used only for type merging. */
262 : 2236282 : gcc_checking_assert (in_lto_p || flag_lto || flag_generate_offload);
263 : 3103667 : return TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
264 : 2935011 : && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t));
265 : : }
266 : :
267 : : /* If TYPE has mangled ODR name, return it. Otherwise return NULL.
268 : : The function works only when free_lang_data is run. */
269 : :
270 : : inline const char *
271 : 66 : get_odr_name_for_type (tree type)
272 : : {
273 : 66 : tree type_name = TYPE_NAME (type);
274 : 66 : if (type_name == NULL_TREE
275 : 52 : || TREE_CODE (type_name) != TYPE_DECL
276 : 116 : || !DECL_ASSEMBLER_NAME_SET_P (type_name))
277 : : return NULL;
278 : :
279 : 38 : return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (type_name));
280 : : }
281 : :
282 : : /* Return true if we are going to do LTO streaming. */
283 : :
284 : : inline bool
285 : 14483342 : lto_streaming_expected_p ()
286 : : {
287 : : /* Compilation before LTO stremaing. */
288 : 14483342 : if (flag_lto && !in_lto_p && symtab->state < IPA_SSA_AFTER_INLINING)
289 : : return true;
290 : : /* WPA or incremental link. */
291 : 13872263 : return (flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO);
292 : : }
293 : :
294 : : #endif /* GCC_IPA_UTILS_H */
|