annotate gcc/ipa-icf.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Interprocedural Identical Code Folding pass
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 /* Interprocedural Identical Code Folding for functions and
kono
parents:
diff changeset
23 read-only variables.
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 The goal of this transformation is to discover functions and read-only
kono
parents:
diff changeset
26 variables which do have exactly the same semantics.
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 In case of functions,
kono
parents:
diff changeset
29 we could either create a virtual clone or do a simple function wrapper
kono
parents:
diff changeset
30 that will call equivalent function. If the function is just locally visible,
kono
parents:
diff changeset
31 all function calls can be redirected. For read-only variables, we create
kono
parents:
diff changeset
32 aliases if possible.
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 Optimization pass arranges as follows:
kono
parents:
diff changeset
35 1) All functions and read-only variables are visited and internal
kono
parents:
diff changeset
36 data structure, either sem_function or sem_variables is created.
kono
parents:
diff changeset
37 2) For every symbol from the previous step, VAR_DECL and FUNCTION_DECL are
kono
parents:
diff changeset
38 saved and matched to corresponding sem_items.
kono
parents:
diff changeset
39 3) These declaration are ignored for equality check and are solved
kono
parents:
diff changeset
40 by Value Numbering algorithm published by Alpert, Zadeck in 1992.
kono
parents:
diff changeset
41 4) We compute hash value for each symbol.
kono
parents:
diff changeset
42 5) Congruence classes are created based on hash value. If hash value are
kono
parents:
diff changeset
43 equal, equals function is called and symbols are deeply compared.
kono
parents:
diff changeset
44 We must prove that all SSA names, declarations and other items
kono
parents:
diff changeset
45 correspond.
kono
parents:
diff changeset
46 6) Value Numbering is executed for these classes. At the end of the process
kono
parents:
diff changeset
47 all symbol members in remaining classes can be merged.
kono
parents:
diff changeset
48 7) Merge operation creates alias in case of read-only variables. For
kono
parents:
diff changeset
49 callgraph node, we must decide if we can redirect local calls,
kono
parents:
diff changeset
50 create an alias or a thunk.
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 */
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 #include "config.h"
kono
parents:
diff changeset
55 #include "system.h"
kono
parents:
diff changeset
56 #include "coretypes.h"
kono
parents:
diff changeset
57 #include "backend.h"
kono
parents:
diff changeset
58 #include "target.h"
kono
parents:
diff changeset
59 #include "rtl.h"
kono
parents:
diff changeset
60 #include "tree.h"
kono
parents:
diff changeset
61 #include "gimple.h"
kono
parents:
diff changeset
62 #include "alloc-pool.h"
kono
parents:
diff changeset
63 #include "tree-pass.h"
kono
parents:
diff changeset
64 #include "ssa.h"
kono
parents:
diff changeset
65 #include "cgraph.h"
kono
parents:
diff changeset
66 #include "coverage.h"
kono
parents:
diff changeset
67 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
68 #include "data-streamer.h"
kono
parents:
diff changeset
69 #include "fold-const.h"
kono
parents:
diff changeset
70 #include "calls.h"
kono
parents:
diff changeset
71 #include "varasm.h"
kono
parents:
diff changeset
72 #include "gimple-iterator.h"
kono
parents:
diff changeset
73 #include "tree-cfg.h"
kono
parents:
diff changeset
74 #include "symbol-summary.h"
kono
parents:
diff changeset
75 #include "ipa-prop.h"
kono
parents:
diff changeset
76 #include "ipa-fnsummary.h"
kono
parents:
diff changeset
77 #include "except.h"
kono
parents:
diff changeset
78 #include "attribs.h"
kono
parents:
diff changeset
79 #include "print-tree.h"
kono
parents:
diff changeset
80 #include "ipa-utils.h"
kono
parents:
diff changeset
81 #include "ipa-icf-gimple.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
82 #include "fibonacci_heap.h"
111
kono
parents:
diff changeset
83 #include "ipa-icf.h"
kono
parents:
diff changeset
84 #include "stor-layout.h"
kono
parents:
diff changeset
85 #include "dbgcnt.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
86 #include "tree-vector-builder.h"
111
kono
parents:
diff changeset
87
kono
parents:
diff changeset
88 using namespace ipa_icf_gimple;
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 namespace ipa_icf {
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 /* Initialization and computation of symtab node hash, there data
kono
parents:
diff changeset
93 are propagated later on. */
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 static sem_item_optimizer *optimizer = NULL;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 /* Constructor. */
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 symbol_compare_collection::symbol_compare_collection (symtab_node *node)
kono
parents:
diff changeset
100 {
kono
parents:
diff changeset
101 m_references.create (0);
kono
parents:
diff changeset
102 m_interposables.create (0);
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 ipa_ref *ref;
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 if (is_a <varpool_node *> (node) && DECL_VIRTUAL_P (node->decl))
kono
parents:
diff changeset
107 return;
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
kono
parents:
diff changeset
110 {
kono
parents:
diff changeset
111 if (ref->address_matters_p ())
kono
parents:
diff changeset
112 m_references.safe_push (ref->referred);
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 if (ref->referred->get_availability () <= AVAIL_INTERPOSABLE)
kono
parents:
diff changeset
115 {
kono
parents:
diff changeset
116 if (ref->address_matters_p ())
kono
parents:
diff changeset
117 m_references.safe_push (ref->referred);
kono
parents:
diff changeset
118 else
kono
parents:
diff changeset
119 m_interposables.safe_push (ref->referred);
kono
parents:
diff changeset
120 }
kono
parents:
diff changeset
121 }
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 if (is_a <cgraph_node *> (node))
kono
parents:
diff changeset
124 {
kono
parents:
diff changeset
125 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 for (cgraph_edge *e = cnode->callees; e; e = e->next_callee)
kono
parents:
diff changeset
128 if (e->callee->get_availability () <= AVAIL_INTERPOSABLE)
kono
parents:
diff changeset
129 m_interposables.safe_push (e->callee);
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131 }
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 /* Constructor for key value pair, where _ITEM is key and _INDEX is a target. */
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 sem_usage_pair::sem_usage_pair (sem_item *_item, unsigned int _index)
kono
parents:
diff changeset
136 : item (_item), index (_index)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 }
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 sem_item::sem_item (sem_item_type _type, bitmap_obstack *stack)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
141 : type (_type), referenced_by_count (0), m_hash (-1), m_hash_set (false)
111
kono
parents:
diff changeset
142 {
kono
parents:
diff changeset
143 setup (stack);
kono
parents:
diff changeset
144 }
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 sem_item::sem_item (sem_item_type _type, symtab_node *_node,
kono
parents:
diff changeset
147 bitmap_obstack *stack)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
148 : type (_type), node (_node), referenced_by_count (0), m_hash (-1),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
149 m_hash_set (false)
111
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 decl = node->decl;
kono
parents:
diff changeset
152 setup (stack);
kono
parents:
diff changeset
153 }
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 /* Add reference to a semantic TARGET. */
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
158 sem_item::add_reference (ref_map *refs,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
159 sem_item *target)
111
kono
parents:
diff changeset
160 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
161 unsigned index = reference_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
162 bool existed;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
163
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
164 vec<sem_item *> &v
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
165 = refs->get_or_insert (new sem_usage_pair (target, index), &existed);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
166 v.safe_push (this);
111
kono
parents:
diff changeset
167 bitmap_set_bit (target->usage_index_bitmap, index);
kono
parents:
diff changeset
168 refs_set.add (target->node);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
169 ++target->referenced_by_count;
111
kono
parents:
diff changeset
170 }
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 /* Initialize internal data structures. Bitmap STACK is used for
kono
parents:
diff changeset
173 bitmap memory allocation process. */
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 void
kono
parents:
diff changeset
176 sem_item::setup (bitmap_obstack *stack)
kono
parents:
diff changeset
177 {
kono
parents:
diff changeset
178 gcc_checking_assert (node);
kono
parents:
diff changeset
179
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
180 reference_count = 0;
111
kono
parents:
diff changeset
181 tree_refs.create (0);
kono
parents:
diff changeset
182 usage_index_bitmap = BITMAP_ALLOC (stack);
kono
parents:
diff changeset
183 }
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 sem_item::~sem_item ()
kono
parents:
diff changeset
186 {
kono
parents:
diff changeset
187 tree_refs.release ();
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 BITMAP_FREE (usage_index_bitmap);
kono
parents:
diff changeset
190 }
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 /* Dump function for debugging purpose. */
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 DEBUG_FUNCTION void
kono
parents:
diff changeset
195 sem_item::dump (void)
kono
parents:
diff changeset
196 {
kono
parents:
diff changeset
197 if (dump_file)
kono
parents:
diff changeset
198 {
kono
parents:
diff changeset
199 fprintf (dump_file, "[%s] %s (tree:%p)\n", type == FUNC ? "func" : "var",
kono
parents:
diff changeset
200 node->dump_name (), (void *) node->decl);
kono
parents:
diff changeset
201 fprintf (dump_file, " hash: %u\n", get_hash ());
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203 }
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 /* Return true if target supports alias symbols. */
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 bool
kono
parents:
diff changeset
208 sem_item::target_supports_symbol_aliases_p (void)
kono
parents:
diff changeset
209 {
kono
parents:
diff changeset
210 #if !defined (ASM_OUTPUT_DEF) || (!defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL))
kono
parents:
diff changeset
211 return false;
kono
parents:
diff changeset
212 #else
kono
parents:
diff changeset
213 return true;
kono
parents:
diff changeset
214 #endif
kono
parents:
diff changeset
215 }
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 void sem_item::set_hash (hashval_t hash)
kono
parents:
diff changeset
218 {
kono
parents:
diff changeset
219 m_hash = hash;
kono
parents:
diff changeset
220 m_hash_set = true;
kono
parents:
diff changeset
221 }
kono
parents:
diff changeset
222
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
223 hash_map<const_tree, hashval_t> sem_item::m_type_hash_cache;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
224
111
kono
parents:
diff changeset
225 /* Semantic function constructor that uses STACK as bitmap memory stack. */
kono
parents:
diff changeset
226
kono
parents:
diff changeset
227 sem_function::sem_function (bitmap_obstack *stack)
kono
parents:
diff changeset
228 : sem_item (FUNC, stack), m_checker (NULL), m_compared_func (NULL)
kono
parents:
diff changeset
229 {
kono
parents:
diff changeset
230 bb_sizes.create (0);
kono
parents:
diff changeset
231 bb_sorted.create (0);
kono
parents:
diff changeset
232 }
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 sem_function::sem_function (cgraph_node *node, bitmap_obstack *stack)
kono
parents:
diff changeset
235 : sem_item (FUNC, node, stack), m_checker (NULL), m_compared_func (NULL)
kono
parents:
diff changeset
236 {
kono
parents:
diff changeset
237 bb_sizes.create (0);
kono
parents:
diff changeset
238 bb_sorted.create (0);
kono
parents:
diff changeset
239 }
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 sem_function::~sem_function ()
kono
parents:
diff changeset
242 {
kono
parents:
diff changeset
243 for (unsigned i = 0; i < bb_sorted.length (); i++)
kono
parents:
diff changeset
244 delete (bb_sorted[i]);
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 bb_sizes.release ();
kono
parents:
diff changeset
247 bb_sorted.release ();
kono
parents:
diff changeset
248 }
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 /* Calculates hash value based on a BASIC_BLOCK. */
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 hashval_t
kono
parents:
diff changeset
253 sem_function::get_bb_hash (const sem_bb *basic_block)
kono
parents:
diff changeset
254 {
kono
parents:
diff changeset
255 inchash::hash hstate;
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 hstate.add_int (basic_block->nondbg_stmt_count);
kono
parents:
diff changeset
258 hstate.add_int (basic_block->edge_count);
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 return hstate.end ();
kono
parents:
diff changeset
261 }
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 /* References independent hash function. */
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 hashval_t
kono
parents:
diff changeset
266 sem_function::get_hash (void)
kono
parents:
diff changeset
267 {
kono
parents:
diff changeset
268 if (!m_hash_set)
kono
parents:
diff changeset
269 {
kono
parents:
diff changeset
270 inchash::hash hstate;
kono
parents:
diff changeset
271 hstate.add_int (177454); /* Random number for function type. */
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 hstate.add_int (arg_count);
kono
parents:
diff changeset
274 hstate.add_int (cfg_checksum);
kono
parents:
diff changeset
275 hstate.add_int (gcode_hash);
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 for (unsigned i = 0; i < bb_sorted.length (); i++)
kono
parents:
diff changeset
278 hstate.merge_hash (get_bb_hash (bb_sorted[i]));
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 for (unsigned i = 0; i < bb_sizes.length (); i++)
kono
parents:
diff changeset
281 hstate.add_int (bb_sizes[i]);
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 /* Add common features of declaration itself. */
kono
parents:
diff changeset
284 if (DECL_FUNCTION_SPECIFIC_TARGET (decl))
kono
parents:
diff changeset
285 hstate.add_hwi
kono
parents:
diff changeset
286 (cl_target_option_hash
kono
parents:
diff changeset
287 (TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (decl))));
kono
parents:
diff changeset
288 if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
kono
parents:
diff changeset
289 hstate.add_hwi
kono
parents:
diff changeset
290 (cl_optimization_hash
kono
parents:
diff changeset
291 (TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))));
kono
parents:
diff changeset
292 hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
kono
parents:
diff changeset
293 hstate.add_flag (DECL_CXX_DESTRUCTOR_P (decl));
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 set_hash (hstate.end ());
kono
parents:
diff changeset
296 }
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 return m_hash;
kono
parents:
diff changeset
299 }
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 /* Compare properties of symbols N1 and N2 that does not affect semantics of
kono
parents:
diff changeset
302 symbol itself but affects semantics of its references from USED_BY (which
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
303 may be NULL if it is unknown). If comparison is false, symbols
111
kono
parents:
diff changeset
304 can still be merged but any symbols referring them can't.
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 If ADDRESS is true, do extra checking needed for IPA_REF_ADDR.
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 TODO: We can also split attributes to those that determine codegen of
kono
parents:
diff changeset
309 a function body/variable constructor itself and those that are used when
kono
parents:
diff changeset
310 referring to it. */
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 bool
kono
parents:
diff changeset
313 sem_item::compare_referenced_symbol_properties (symtab_node *used_by,
kono
parents:
diff changeset
314 symtab_node *n1,
kono
parents:
diff changeset
315 symtab_node *n2,
kono
parents:
diff changeset
316 bool address)
kono
parents:
diff changeset
317 {
kono
parents:
diff changeset
318 if (is_a <cgraph_node *> (n1))
kono
parents:
diff changeset
319 {
kono
parents:
diff changeset
320 /* Inline properties matters: we do now want to merge uses of inline
kono
parents:
diff changeset
321 function to uses of normal function because inline hint would be lost.
kono
parents:
diff changeset
322 We however can merge inline function to noinline because the alias
kono
parents:
diff changeset
323 will keep its DECL_DECLARED_INLINE flag.
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 Also ignore inline flag when optimizing for size or when function
kono
parents:
diff changeset
326 is known to not be inlinable.
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 TODO: the optimize_size checks can also be assumed to be true if
kono
parents:
diff changeset
329 unit has no !optimize_size functions. */
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 if ((!used_by || address || !is_a <cgraph_node *> (used_by)
kono
parents:
diff changeset
332 || !opt_for_fn (used_by->decl, optimize_size))
kono
parents:
diff changeset
333 && !opt_for_fn (n1->decl, optimize_size)
kono
parents:
diff changeset
334 && n1->get_availability () > AVAIL_INTERPOSABLE
kono
parents:
diff changeset
335 && (!DECL_UNINLINABLE (n1->decl) || !DECL_UNINLINABLE (n2->decl)))
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 if (DECL_DISREGARD_INLINE_LIMITS (n1->decl)
kono
parents:
diff changeset
338 != DECL_DISREGARD_INLINE_LIMITS (n2->decl))
kono
parents:
diff changeset
339 return return_false_with_msg
kono
parents:
diff changeset
340 ("DECL_DISREGARD_INLINE_LIMITS are different");
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 if (DECL_DECLARED_INLINE_P (n1->decl)
kono
parents:
diff changeset
343 != DECL_DECLARED_INLINE_P (n2->decl))
kono
parents:
diff changeset
344 return return_false_with_msg ("inline attributes are different");
kono
parents:
diff changeset
345 }
kono
parents:
diff changeset
346
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
347 if (DECL_IS_OPERATOR_NEW_P (n1->decl)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
348 != DECL_IS_OPERATOR_NEW_P (n2->decl))
111
kono
parents:
diff changeset
349 return return_false_with_msg ("operator new flags are different");
kono
parents:
diff changeset
350 }
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 /* Merging two definitions with a reference to equivalent vtables, but
kono
parents:
diff changeset
353 belonging to a different type may result in ipa-polymorphic-call analysis
kono
parents:
diff changeset
354 giving a wrong answer about the dynamic type of instance. */
kono
parents:
diff changeset
355 if (is_a <varpool_node *> (n1))
kono
parents:
diff changeset
356 {
kono
parents:
diff changeset
357 if ((DECL_VIRTUAL_P (n1->decl) || DECL_VIRTUAL_P (n2->decl))
kono
parents:
diff changeset
358 && (DECL_VIRTUAL_P (n1->decl) != DECL_VIRTUAL_P (n2->decl)
kono
parents:
diff changeset
359 || !types_must_be_same_for_odr (DECL_CONTEXT (n1->decl),
kono
parents:
diff changeset
360 DECL_CONTEXT (n2->decl)))
kono
parents:
diff changeset
361 && (!used_by || !is_a <cgraph_node *> (used_by) || address
kono
parents:
diff changeset
362 || opt_for_fn (used_by->decl, flag_devirtualize)))
kono
parents:
diff changeset
363 return return_false_with_msg
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
364 ("references to virtual tables cannot be merged");
111
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 if (address && DECL_ALIGN (n1->decl) != DECL_ALIGN (n2->decl))
kono
parents:
diff changeset
367 return return_false_with_msg ("alignment mismatch");
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 /* For functions we compare attributes in equals_wpa, because we do
kono
parents:
diff changeset
370 not know what attributes may cause codegen differences, but for
kono
parents:
diff changeset
371 variables just compare attributes for references - the codegen
kono
parents:
diff changeset
372 for constructors is affected only by those attributes that we lower
kono
parents:
diff changeset
373 to explicit representation (such as DECL_ALIGN or DECL_SECTION). */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
374 if (!attribute_list_equal (DECL_ATTRIBUTES (n1->decl),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
375 DECL_ATTRIBUTES (n2->decl)))
111
kono
parents:
diff changeset
376 return return_false_with_msg ("different var decl attributes");
kono
parents:
diff changeset
377 if (comp_type_attributes (TREE_TYPE (n1->decl),
kono
parents:
diff changeset
378 TREE_TYPE (n2->decl)) != 1)
kono
parents:
diff changeset
379 return return_false_with_msg ("different var type attributes");
kono
parents:
diff changeset
380 }
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 /* When matching virtual tables, be sure to also match information
kono
parents:
diff changeset
383 relevant for polymorphic call analysis. */
kono
parents:
diff changeset
384 if (used_by && is_a <varpool_node *> (used_by)
kono
parents:
diff changeset
385 && DECL_VIRTUAL_P (used_by->decl))
kono
parents:
diff changeset
386 {
kono
parents:
diff changeset
387 if (DECL_VIRTUAL_P (n1->decl) != DECL_VIRTUAL_P (n2->decl))
kono
parents:
diff changeset
388 return return_false_with_msg ("virtual flag mismatch");
kono
parents:
diff changeset
389 if (DECL_VIRTUAL_P (n1->decl) && is_a <cgraph_node *> (n1)
kono
parents:
diff changeset
390 && (DECL_FINAL_P (n1->decl) != DECL_FINAL_P (n2->decl)))
kono
parents:
diff changeset
391 return return_false_with_msg ("final flag mismatch");
kono
parents:
diff changeset
392 }
kono
parents:
diff changeset
393 return true;
kono
parents:
diff changeset
394 }
kono
parents:
diff changeset
395
kono
parents:
diff changeset
396 /* Hash properties that are compared by compare_referenced_symbol_properties. */
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 void
kono
parents:
diff changeset
399 sem_item::hash_referenced_symbol_properties (symtab_node *ref,
kono
parents:
diff changeset
400 inchash::hash &hstate,
kono
parents:
diff changeset
401 bool address)
kono
parents:
diff changeset
402 {
kono
parents:
diff changeset
403 if (is_a <cgraph_node *> (ref))
kono
parents:
diff changeset
404 {
kono
parents:
diff changeset
405 if ((type != FUNC || address || !opt_for_fn (decl, optimize_size))
kono
parents:
diff changeset
406 && !opt_for_fn (ref->decl, optimize_size)
kono
parents:
diff changeset
407 && !DECL_UNINLINABLE (ref->decl))
kono
parents:
diff changeset
408 {
kono
parents:
diff changeset
409 hstate.add_flag (DECL_DISREGARD_INLINE_LIMITS (ref->decl));
kono
parents:
diff changeset
410 hstate.add_flag (DECL_DECLARED_INLINE_P (ref->decl));
kono
parents:
diff changeset
411 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
412 hstate.add_flag (DECL_IS_OPERATOR_NEW_P (ref->decl));
111
kono
parents:
diff changeset
413 }
kono
parents:
diff changeset
414 else if (is_a <varpool_node *> (ref))
kono
parents:
diff changeset
415 {
kono
parents:
diff changeset
416 hstate.add_flag (DECL_VIRTUAL_P (ref->decl));
kono
parents:
diff changeset
417 if (address)
kono
parents:
diff changeset
418 hstate.add_int (DECL_ALIGN (ref->decl));
kono
parents:
diff changeset
419 }
kono
parents:
diff changeset
420 }
kono
parents:
diff changeset
421
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 /* For a given symbol table nodes N1 and N2, we check that FUNCTION_DECLs
kono
parents:
diff changeset
424 point to a same function. Comparison can be skipped if IGNORED_NODES
kono
parents:
diff changeset
425 contains these nodes. ADDRESS indicate if address is taken. */
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 bool
kono
parents:
diff changeset
428 sem_item::compare_symbol_references (
kono
parents:
diff changeset
429 hash_map <symtab_node *, sem_item *> &ignored_nodes,
kono
parents:
diff changeset
430 symtab_node *n1, symtab_node *n2, bool address)
kono
parents:
diff changeset
431 {
kono
parents:
diff changeset
432 enum availability avail1, avail2;
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 if (n1 == n2)
kono
parents:
diff changeset
435 return true;
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 /* Never match variable and function. */
kono
parents:
diff changeset
438 if (is_a <varpool_node *> (n1) != is_a <varpool_node *> (n2))
kono
parents:
diff changeset
439 return false;
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 if (!compare_referenced_symbol_properties (node, n1, n2, address))
kono
parents:
diff changeset
442 return false;
kono
parents:
diff changeset
443 if (address && n1->equal_address_to (n2) == 1)
kono
parents:
diff changeset
444 return true;
kono
parents:
diff changeset
445 if (!address && n1->semantically_equivalent_p (n2))
kono
parents:
diff changeset
446 return true;
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 n1 = n1->ultimate_alias_target (&avail1);
kono
parents:
diff changeset
449 n2 = n2->ultimate_alias_target (&avail2);
kono
parents:
diff changeset
450
kono
parents:
diff changeset
451 if (avail1 > AVAIL_INTERPOSABLE && ignored_nodes.get (n1)
kono
parents:
diff changeset
452 && avail2 > AVAIL_INTERPOSABLE && ignored_nodes.get (n2))
kono
parents:
diff changeset
453 return true;
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 return return_false_with_msg ("different references");
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 /* If cgraph edges E1 and E2 are indirect calls, verify that
kono
parents:
diff changeset
459 ECF flags are the same. */
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 bool sem_function::compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2)
kono
parents:
diff changeset
462 {
kono
parents:
diff changeset
463 if (e1->indirect_info && e2->indirect_info)
kono
parents:
diff changeset
464 {
kono
parents:
diff changeset
465 int e1_flags = e1->indirect_info->ecf_flags;
kono
parents:
diff changeset
466 int e2_flags = e2->indirect_info->ecf_flags;
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 if (e1_flags != e2_flags)
kono
parents:
diff changeset
469 return return_false_with_msg ("ICF flags are different");
kono
parents:
diff changeset
470 }
kono
parents:
diff changeset
471 else if (e1->indirect_info || e2->indirect_info)
kono
parents:
diff changeset
472 return false;
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 return true;
kono
parents:
diff changeset
475 }
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 /* Return true if parameter I may be used. */
kono
parents:
diff changeset
478
kono
parents:
diff changeset
479 bool
kono
parents:
diff changeset
480 sem_function::param_used_p (unsigned int i)
kono
parents:
diff changeset
481 {
kono
parents:
diff changeset
482 if (ipa_node_params_sum == NULL)
kono
parents:
diff changeset
483 return true;
kono
parents:
diff changeset
484
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
485 class ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
486
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
487 if (!parms_info || vec_safe_length (parms_info->descriptors) <= i)
111
kono
parents:
diff changeset
488 return true;
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
kono
parents:
diff changeset
491 }
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 /* Perform additional check needed to match types function parameters that are
kono
parents:
diff changeset
494 used. Unlike for normal decls it matters if type is TYPE_RESTRICT and we
kono
parents:
diff changeset
495 make an assumption that REFERENCE_TYPE parameters are always non-NULL. */
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 bool
kono
parents:
diff changeset
498 sem_function::compatible_parm_types_p (tree parm1, tree parm2)
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 /* Be sure that parameters are TBAA compatible. */
kono
parents:
diff changeset
501 if (!func_checker::compatible_types_p (parm1, parm2))
kono
parents:
diff changeset
502 return return_false_with_msg ("parameter type is not compatible");
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 if (POINTER_TYPE_P (parm1)
kono
parents:
diff changeset
505 && (TYPE_RESTRICT (parm1) != TYPE_RESTRICT (parm2)))
kono
parents:
diff changeset
506 return return_false_with_msg ("argument restrict flag mismatch");
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 /* nonnull_arg_p implies non-zero range to REFERENCE types. */
kono
parents:
diff changeset
509 if (POINTER_TYPE_P (parm1)
kono
parents:
diff changeset
510 && TREE_CODE (parm1) != TREE_CODE (parm2)
kono
parents:
diff changeset
511 && opt_for_fn (decl, flag_delete_null_pointer_checks))
kono
parents:
diff changeset
512 return return_false_with_msg ("pointer wrt reference mismatch");
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 return true;
kono
parents:
diff changeset
515 }
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 /* Fast equality function based on knowledge known in WPA. */
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 bool
kono
parents:
diff changeset
520 sem_function::equals_wpa (sem_item *item,
kono
parents:
diff changeset
521 hash_map <symtab_node *, sem_item *> &ignored_nodes)
kono
parents:
diff changeset
522 {
kono
parents:
diff changeset
523 gcc_assert (item->type == FUNC);
kono
parents:
diff changeset
524 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
kono
parents:
diff changeset
525 cgraph_node *cnode2 = dyn_cast <cgraph_node *> (item->node);
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 m_compared_func = static_cast<sem_function *> (item);
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 if (cnode->thunk.thunk_p != cnode2->thunk.thunk_p)
kono
parents:
diff changeset
530 return return_false_with_msg ("thunk_p mismatch");
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 if (cnode->thunk.thunk_p)
kono
parents:
diff changeset
533 {
kono
parents:
diff changeset
534 if (cnode->thunk.fixed_offset != cnode2->thunk.fixed_offset)
kono
parents:
diff changeset
535 return return_false_with_msg ("thunk fixed_offset mismatch");
kono
parents:
diff changeset
536 if (cnode->thunk.virtual_value != cnode2->thunk.virtual_value)
kono
parents:
diff changeset
537 return return_false_with_msg ("thunk virtual_value mismatch");
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
538 if (cnode->thunk.indirect_offset != cnode2->thunk.indirect_offset)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
539 return return_false_with_msg ("thunk indirect_offset mismatch");
111
kono
parents:
diff changeset
540 if (cnode->thunk.this_adjusting != cnode2->thunk.this_adjusting)
kono
parents:
diff changeset
541 return return_false_with_msg ("thunk this_adjusting mismatch");
kono
parents:
diff changeset
542 if (cnode->thunk.virtual_offset_p != cnode2->thunk.virtual_offset_p)
kono
parents:
diff changeset
543 return return_false_with_msg ("thunk virtual_offset_p mismatch");
kono
parents:
diff changeset
544 }
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 /* Compare special function DECL attributes. */
kono
parents:
diff changeset
547 if (DECL_FUNCTION_PERSONALITY (decl)
kono
parents:
diff changeset
548 != DECL_FUNCTION_PERSONALITY (item->decl))
kono
parents:
diff changeset
549 return return_false_with_msg ("function personalities are different");
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 if (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl)
kono
parents:
diff changeset
552 != DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (item->decl))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
553 return return_false_with_msg ("instrument function entry exit "
111
kono
parents:
diff changeset
554 "attributes are different");
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 if (DECL_NO_LIMIT_STACK (decl) != DECL_NO_LIMIT_STACK (item->decl))
kono
parents:
diff changeset
557 return return_false_with_msg ("no stack limit attributes are different");
kono
parents:
diff changeset
558
kono
parents:
diff changeset
559 if (DECL_CXX_CONSTRUCTOR_P (decl) != DECL_CXX_CONSTRUCTOR_P (item->decl))
kono
parents:
diff changeset
560 return return_false_with_msg ("DECL_CXX_CONSTRUCTOR mismatch");
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 if (DECL_CXX_DESTRUCTOR_P (decl) != DECL_CXX_DESTRUCTOR_P (item->decl))
kono
parents:
diff changeset
563 return return_false_with_msg ("DECL_CXX_DESTRUCTOR mismatch");
kono
parents:
diff changeset
564
kono
parents:
diff changeset
565 /* TODO: pure/const flags mostly matters only for references, except for
kono
parents:
diff changeset
566 the fact that codegen takes LOOPING flag as a hint that loops are
kono
parents:
diff changeset
567 finite. We may arrange the code to always pick leader that has least
kono
parents:
diff changeset
568 specified flags and then this can go into comparing symbol properties. */
kono
parents:
diff changeset
569 if (flags_from_decl_or_type (decl) != flags_from_decl_or_type (item->decl))
kono
parents:
diff changeset
570 return return_false_with_msg ("decl_or_type flags are different");
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 /* Do not match polymorphic constructors of different types. They calls
kono
parents:
diff changeset
573 type memory location for ipa-polymorphic-call and we do not want
kono
parents:
diff changeset
574 it to get confused by wrong type. */
kono
parents:
diff changeset
575 if (DECL_CXX_CONSTRUCTOR_P (decl)
kono
parents:
diff changeset
576 && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
kono
parents:
diff changeset
577 {
kono
parents:
diff changeset
578 if (TREE_CODE (TREE_TYPE (item->decl)) != METHOD_TYPE)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
579 return return_false_with_msg ("DECL_CXX_CONSTRUCTOR type mismatch");
111
kono
parents:
diff changeset
580 else if (!func_checker::compatible_polymorphic_types_p
kono
parents:
diff changeset
581 (TYPE_METHOD_BASETYPE (TREE_TYPE (decl)),
kono
parents:
diff changeset
582 TYPE_METHOD_BASETYPE (TREE_TYPE (item->decl)), false))
kono
parents:
diff changeset
583 return return_false_with_msg ("ctor polymorphic type mismatch");
kono
parents:
diff changeset
584 }
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 /* Checking function TARGET and OPTIMIZATION flags. */
kono
parents:
diff changeset
587 cl_target_option *tar1 = target_opts_for_fn (decl);
kono
parents:
diff changeset
588 cl_target_option *tar2 = target_opts_for_fn (item->decl);
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 if (tar1 != tar2 && !cl_target_option_eq (tar1, tar2))
kono
parents:
diff changeset
591 {
kono
parents:
diff changeset
592 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
593 {
kono
parents:
diff changeset
594 fprintf (dump_file, "target flags difference");
kono
parents:
diff changeset
595 cl_target_option_print_diff (dump_file, 2, tar1, tar2);
kono
parents:
diff changeset
596 }
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 return return_false_with_msg ("Target flags are different");
kono
parents:
diff changeset
599 }
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 cl_optimization *opt1 = opts_for_fn (decl);
kono
parents:
diff changeset
602 cl_optimization *opt2 = opts_for_fn (item->decl);
kono
parents:
diff changeset
603
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
604 if (opt1 != opt2 && !cl_optimization_option_eq (opt1, opt2))
111
kono
parents:
diff changeset
605 {
kono
parents:
diff changeset
606 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
607 {
kono
parents:
diff changeset
608 fprintf (dump_file, "optimization flags difference");
kono
parents:
diff changeset
609 cl_optimization_print_diff (dump_file, 2, opt1, opt2);
kono
parents:
diff changeset
610 }
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 return return_false_with_msg ("optimization flags are different");
kono
parents:
diff changeset
613 }
kono
parents:
diff changeset
614
kono
parents:
diff changeset
615 /* Result type checking. */
kono
parents:
diff changeset
616 if (!func_checker::compatible_types_p
kono
parents:
diff changeset
617 (TREE_TYPE (TREE_TYPE (decl)),
kono
parents:
diff changeset
618 TREE_TYPE (TREE_TYPE (m_compared_func->decl))))
kono
parents:
diff changeset
619 return return_false_with_msg ("result types are different");
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 /* Checking types of arguments. */
kono
parents:
diff changeset
622 tree list1 = TYPE_ARG_TYPES (TREE_TYPE (decl)),
kono
parents:
diff changeset
623 list2 = TYPE_ARG_TYPES (TREE_TYPE (m_compared_func->decl));
kono
parents:
diff changeset
624 for (unsigned i = 0; list1 && list2;
kono
parents:
diff changeset
625 list1 = TREE_CHAIN (list1), list2 = TREE_CHAIN (list2), i++)
kono
parents:
diff changeset
626 {
kono
parents:
diff changeset
627 tree parm1 = TREE_VALUE (list1);
kono
parents:
diff changeset
628 tree parm2 = TREE_VALUE (list2);
kono
parents:
diff changeset
629
kono
parents:
diff changeset
630 /* This guard is here for function pointer with attributes (pr59927.c). */
kono
parents:
diff changeset
631 if (!parm1 || !parm2)
kono
parents:
diff changeset
632 return return_false_with_msg ("NULL argument type");
kono
parents:
diff changeset
633
kono
parents:
diff changeset
634 /* Verify that types are compatible to ensure that both functions
kono
parents:
diff changeset
635 have same calling conventions. */
kono
parents:
diff changeset
636 if (!types_compatible_p (parm1, parm2))
kono
parents:
diff changeset
637 return return_false_with_msg ("parameter types are not compatible");
kono
parents:
diff changeset
638
kono
parents:
diff changeset
639 if (!param_used_p (i))
kono
parents:
diff changeset
640 continue;
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 /* Perform additional checks for used parameters. */
kono
parents:
diff changeset
643 if (!compatible_parm_types_p (parm1, parm2))
kono
parents:
diff changeset
644 return false;
kono
parents:
diff changeset
645 }
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 if (list1 || list2)
kono
parents:
diff changeset
648 return return_false_with_msg ("Mismatched number of parameters");
kono
parents:
diff changeset
649
kono
parents:
diff changeset
650 if (node->num_references () != item->node->num_references ())
kono
parents:
diff changeset
651 return return_false_with_msg ("different number of references");
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 /* Checking function attributes.
kono
parents:
diff changeset
654 This is quadratic in number of attributes */
kono
parents:
diff changeset
655 if (comp_type_attributes (TREE_TYPE (decl),
kono
parents:
diff changeset
656 TREE_TYPE (item->decl)) != 1)
kono
parents:
diff changeset
657 return return_false_with_msg ("different type attributes");
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
658 if (!attribute_list_equal (DECL_ATTRIBUTES (decl),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
659 DECL_ATTRIBUTES (item->decl)))
111
kono
parents:
diff changeset
660 return return_false_with_msg ("different decl attributes");
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 /* The type of THIS pointer type memory location for
kono
parents:
diff changeset
663 ipa-polymorphic-call-analysis. */
kono
parents:
diff changeset
664 if (opt_for_fn (decl, flag_devirtualize)
kono
parents:
diff changeset
665 && (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
kono
parents:
diff changeset
666 || TREE_CODE (TREE_TYPE (item->decl)) == METHOD_TYPE)
kono
parents:
diff changeset
667 && param_used_p (0)
kono
parents:
diff changeset
668 && compare_polymorphic_p ())
kono
parents:
diff changeset
669 {
kono
parents:
diff changeset
670 if (TREE_CODE (TREE_TYPE (decl)) != TREE_CODE (TREE_TYPE (item->decl)))
kono
parents:
diff changeset
671 return return_false_with_msg ("METHOD_TYPE and FUNCTION_TYPE mismatch");
kono
parents:
diff changeset
672 if (!func_checker::compatible_polymorphic_types_p
kono
parents:
diff changeset
673 (TYPE_METHOD_BASETYPE (TREE_TYPE (decl)),
kono
parents:
diff changeset
674 TYPE_METHOD_BASETYPE (TREE_TYPE (item->decl)), false))
kono
parents:
diff changeset
675 return return_false_with_msg ("THIS pointer ODR type mismatch");
kono
parents:
diff changeset
676 }
kono
parents:
diff changeset
677
kono
parents:
diff changeset
678 ipa_ref *ref = NULL, *ref2 = NULL;
kono
parents:
diff changeset
679 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
kono
parents:
diff changeset
680 {
kono
parents:
diff changeset
681 item->node->iterate_reference (i, ref2);
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 if (ref->use != ref2->use)
kono
parents:
diff changeset
684 return return_false_with_msg ("reference use mismatch");
kono
parents:
diff changeset
685
kono
parents:
diff changeset
686 if (!compare_symbol_references (ignored_nodes, ref->referred,
kono
parents:
diff changeset
687 ref2->referred,
kono
parents:
diff changeset
688 ref->address_matters_p ()))
kono
parents:
diff changeset
689 return false;
kono
parents:
diff changeset
690 }
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 cgraph_edge *e1 = dyn_cast <cgraph_node *> (node)->callees;
kono
parents:
diff changeset
693 cgraph_edge *e2 = dyn_cast <cgraph_node *> (item->node)->callees;
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 while (e1 && e2)
kono
parents:
diff changeset
696 {
kono
parents:
diff changeset
697 if (!compare_symbol_references (ignored_nodes, e1->callee,
kono
parents:
diff changeset
698 e2->callee, false))
kono
parents:
diff changeset
699 return false;
kono
parents:
diff changeset
700 if (!compare_edge_flags (e1, e2))
kono
parents:
diff changeset
701 return false;
kono
parents:
diff changeset
702
kono
parents:
diff changeset
703 e1 = e1->next_callee;
kono
parents:
diff changeset
704 e2 = e2->next_callee;
kono
parents:
diff changeset
705 }
kono
parents:
diff changeset
706
kono
parents:
diff changeset
707 if (e1 || e2)
kono
parents:
diff changeset
708 return return_false_with_msg ("different number of calls");
kono
parents:
diff changeset
709
kono
parents:
diff changeset
710 e1 = dyn_cast <cgraph_node *> (node)->indirect_calls;
kono
parents:
diff changeset
711 e2 = dyn_cast <cgraph_node *> (item->node)->indirect_calls;
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 while (e1 && e2)
kono
parents:
diff changeset
714 {
kono
parents:
diff changeset
715 if (!compare_edge_flags (e1, e2))
kono
parents:
diff changeset
716 return false;
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 e1 = e1->next_callee;
kono
parents:
diff changeset
719 e2 = e2->next_callee;
kono
parents:
diff changeset
720 }
kono
parents:
diff changeset
721
kono
parents:
diff changeset
722 if (e1 || e2)
kono
parents:
diff changeset
723 return return_false_with_msg ("different number of indirect calls");
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 return true;
kono
parents:
diff changeset
726 }
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 /* Update hash by address sensitive references. We iterate over all
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
729 sensitive references (address_matters_p) and we hash ultimate alias
111
kono
parents:
diff changeset
730 target of these nodes, which can improve a semantic item hash.
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 Also hash in referenced symbols properties. This can be done at any time
kono
parents:
diff changeset
733 (as the properties should not change), but it is convenient to do it here
kono
parents:
diff changeset
734 while we walk the references anyway. */
kono
parents:
diff changeset
735
kono
parents:
diff changeset
736 void
kono
parents:
diff changeset
737 sem_item::update_hash_by_addr_refs (hash_map <symtab_node *,
kono
parents:
diff changeset
738 sem_item *> &m_symtab_node_map)
kono
parents:
diff changeset
739 {
kono
parents:
diff changeset
740 ipa_ref* ref;
kono
parents:
diff changeset
741 inchash::hash hstate (get_hash ());
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
kono
parents:
diff changeset
744 {
kono
parents:
diff changeset
745 hstate.add_int (ref->use);
kono
parents:
diff changeset
746 hash_referenced_symbol_properties (ref->referred, hstate,
kono
parents:
diff changeset
747 ref->use == IPA_REF_ADDR);
kono
parents:
diff changeset
748 if (ref->address_matters_p () || !m_symtab_node_map.get (ref->referred))
kono
parents:
diff changeset
749 hstate.add_int (ref->referred->ultimate_alias_target ()->order);
kono
parents:
diff changeset
750 }
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 if (is_a <cgraph_node *> (node))
kono
parents:
diff changeset
753 {
kono
parents:
diff changeset
754 for (cgraph_edge *e = dyn_cast <cgraph_node *> (node)->callers; e;
kono
parents:
diff changeset
755 e = e->next_caller)
kono
parents:
diff changeset
756 {
kono
parents:
diff changeset
757 sem_item **result = m_symtab_node_map.get (e->callee);
kono
parents:
diff changeset
758 hash_referenced_symbol_properties (e->callee, hstate, false);
kono
parents:
diff changeset
759 if (!result)
kono
parents:
diff changeset
760 hstate.add_int (e->callee->ultimate_alias_target ()->order);
kono
parents:
diff changeset
761 }
kono
parents:
diff changeset
762 }
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 set_hash (hstate.end ());
kono
parents:
diff changeset
765 }
kono
parents:
diff changeset
766
kono
parents:
diff changeset
767 /* Update hash by computed local hash values taken from different
kono
parents:
diff changeset
768 semantic items.
kono
parents:
diff changeset
769 TODO: stronger SCC based hashing would be desirable here. */
kono
parents:
diff changeset
770
kono
parents:
diff changeset
771 void
kono
parents:
diff changeset
772 sem_item::update_hash_by_local_refs (hash_map <symtab_node *,
kono
parents:
diff changeset
773 sem_item *> &m_symtab_node_map)
kono
parents:
diff changeset
774 {
kono
parents:
diff changeset
775 ipa_ref* ref;
kono
parents:
diff changeset
776 inchash::hash state (get_hash ());
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 for (unsigned j = 0; node->iterate_reference (j, ref); j++)
kono
parents:
diff changeset
779 {
kono
parents:
diff changeset
780 sem_item **result = m_symtab_node_map.get (ref->referring);
kono
parents:
diff changeset
781 if (result)
kono
parents:
diff changeset
782 state.merge_hash ((*result)->get_hash ());
kono
parents:
diff changeset
783 }
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 if (type == FUNC)
kono
parents:
diff changeset
786 {
kono
parents:
diff changeset
787 for (cgraph_edge *e = dyn_cast <cgraph_node *> (node)->callees; e;
kono
parents:
diff changeset
788 e = e->next_callee)
kono
parents:
diff changeset
789 {
kono
parents:
diff changeset
790 sem_item **result = m_symtab_node_map.get (e->caller);
kono
parents:
diff changeset
791 if (result)
kono
parents:
diff changeset
792 state.merge_hash ((*result)->get_hash ());
kono
parents:
diff changeset
793 }
kono
parents:
diff changeset
794 }
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 global_hash = state.end ();
kono
parents:
diff changeset
797 }
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 /* Returns true if the item equals to ITEM given as argument. */
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 bool
kono
parents:
diff changeset
802 sem_function::equals (sem_item *item,
kono
parents:
diff changeset
803 hash_map <symtab_node *, sem_item *> &)
kono
parents:
diff changeset
804 {
kono
parents:
diff changeset
805 gcc_assert (item->type == FUNC);
kono
parents:
diff changeset
806 bool eq = equals_private (item);
kono
parents:
diff changeset
807
kono
parents:
diff changeset
808 if (m_checker != NULL)
kono
parents:
diff changeset
809 {
kono
parents:
diff changeset
810 delete m_checker;
kono
parents:
diff changeset
811 m_checker = NULL;
kono
parents:
diff changeset
812 }
kono
parents:
diff changeset
813
kono
parents:
diff changeset
814 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
815 fprintf (dump_file,
kono
parents:
diff changeset
816 "Equals called for: %s:%s with result: %s\n\n",
kono
parents:
diff changeset
817 node->dump_name (),
kono
parents:
diff changeset
818 item->node->dump_name (),
kono
parents:
diff changeset
819 eq ? "true" : "false");
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 return eq;
kono
parents:
diff changeset
822 }
kono
parents:
diff changeset
823
kono
parents:
diff changeset
824 /* Processes function equality comparison. */
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 bool
kono
parents:
diff changeset
827 sem_function::equals_private (sem_item *item)
kono
parents:
diff changeset
828 {
kono
parents:
diff changeset
829 if (item->type != FUNC)
kono
parents:
diff changeset
830 return false;
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 basic_block bb1, bb2;
kono
parents:
diff changeset
833 edge e1, e2;
kono
parents:
diff changeset
834 edge_iterator ei1, ei2;
kono
parents:
diff changeset
835 bool result = true;
kono
parents:
diff changeset
836 tree arg1, arg2;
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 m_compared_func = static_cast<sem_function *> (item);
kono
parents:
diff changeset
839
kono
parents:
diff changeset
840 gcc_assert (decl != item->decl);
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 if (bb_sorted.length () != m_compared_func->bb_sorted.length ()
kono
parents:
diff changeset
843 || edge_count != m_compared_func->edge_count
kono
parents:
diff changeset
844 || cfg_checksum != m_compared_func->cfg_checksum)
kono
parents:
diff changeset
845 return return_false ();
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 m_checker = new func_checker (decl, m_compared_func->decl,
kono
parents:
diff changeset
848 false,
kono
parents:
diff changeset
849 &refs_set,
kono
parents:
diff changeset
850 &m_compared_func->refs_set);
kono
parents:
diff changeset
851 arg1 = DECL_ARGUMENTS (decl);
kono
parents:
diff changeset
852 arg2 = DECL_ARGUMENTS (m_compared_func->decl);
kono
parents:
diff changeset
853 for (unsigned i = 0;
kono
parents:
diff changeset
854 arg1 && arg2; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2), i++)
kono
parents:
diff changeset
855 {
kono
parents:
diff changeset
856 if (!types_compatible_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
kono
parents:
diff changeset
857 return return_false_with_msg ("argument types are not compatible");
kono
parents:
diff changeset
858 if (!param_used_p (i))
kono
parents:
diff changeset
859 continue;
kono
parents:
diff changeset
860 /* Perform additional checks for used parameters. */
kono
parents:
diff changeset
861 if (!compatible_parm_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
kono
parents:
diff changeset
862 return false;
kono
parents:
diff changeset
863 if (!m_checker->compare_decl (arg1, arg2))
kono
parents:
diff changeset
864 return return_false ();
kono
parents:
diff changeset
865 }
kono
parents:
diff changeset
866 if (arg1 || arg2)
kono
parents:
diff changeset
867 return return_false_with_msg ("Mismatched number of arguments");
kono
parents:
diff changeset
868
kono
parents:
diff changeset
869 if (!dyn_cast <cgraph_node *> (node)->has_gimple_body_p ())
kono
parents:
diff changeset
870 return true;
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 /* Fill-up label dictionary. */
kono
parents:
diff changeset
873 for (unsigned i = 0; i < bb_sorted.length (); ++i)
kono
parents:
diff changeset
874 {
kono
parents:
diff changeset
875 m_checker->parse_labels (bb_sorted[i]);
kono
parents:
diff changeset
876 m_checker->parse_labels (m_compared_func->bb_sorted[i]);
kono
parents:
diff changeset
877 }
kono
parents:
diff changeset
878
kono
parents:
diff changeset
879 /* Checking all basic blocks. */
kono
parents:
diff changeset
880 for (unsigned i = 0; i < bb_sorted.length (); ++i)
kono
parents:
diff changeset
881 if(!m_checker->compare_bb (bb_sorted[i], m_compared_func->bb_sorted[i]))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
882 return return_false ();
111
kono
parents:
diff changeset
883
kono
parents:
diff changeset
884 auto_vec <int> bb_dict;
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 /* Basic block edges check. */
kono
parents:
diff changeset
887 for (unsigned i = 0; i < bb_sorted.length (); ++i)
kono
parents:
diff changeset
888 {
kono
parents:
diff changeset
889 bb1 = bb_sorted[i]->bb;
kono
parents:
diff changeset
890 bb2 = m_compared_func->bb_sorted[i]->bb;
kono
parents:
diff changeset
891
kono
parents:
diff changeset
892 ei2 = ei_start (bb2->preds);
kono
parents:
diff changeset
893
kono
parents:
diff changeset
894 for (ei1 = ei_start (bb1->preds); ei_cond (ei1, &e1); ei_next (&ei1))
kono
parents:
diff changeset
895 {
kono
parents:
diff changeset
896 ei_cond (ei2, &e2);
kono
parents:
diff changeset
897
kono
parents:
diff changeset
898 if (e1->flags != e2->flags)
kono
parents:
diff changeset
899 return return_false_with_msg ("flags comparison returns false");
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 if (!bb_dict_test (&bb_dict, e1->src->index, e2->src->index))
kono
parents:
diff changeset
902 return return_false_with_msg ("edge comparison returns false");
kono
parents:
diff changeset
903
kono
parents:
diff changeset
904 if (!bb_dict_test (&bb_dict, e1->dest->index, e2->dest->index))
kono
parents:
diff changeset
905 return return_false_with_msg ("BB comparison returns false");
kono
parents:
diff changeset
906
kono
parents:
diff changeset
907 if (!m_checker->compare_edge (e1, e2))
kono
parents:
diff changeset
908 return return_false_with_msg ("edge comparison returns false");
kono
parents:
diff changeset
909
kono
parents:
diff changeset
910 ei_next (&ei2);
kono
parents:
diff changeset
911 }
kono
parents:
diff changeset
912 }
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 /* Basic block PHI nodes comparison. */
kono
parents:
diff changeset
915 for (unsigned i = 0; i < bb_sorted.length (); i++)
kono
parents:
diff changeset
916 if (!compare_phi_node (bb_sorted[i]->bb, m_compared_func->bb_sorted[i]->bb))
kono
parents:
diff changeset
917 return return_false_with_msg ("PHI node comparison returns false");
kono
parents:
diff changeset
918
kono
parents:
diff changeset
919 return result;
kono
parents:
diff changeset
920 }
kono
parents:
diff changeset
921
kono
parents:
diff changeset
922 /* Set LOCAL_P of NODE to true if DATA is non-NULL.
kono
parents:
diff changeset
923 Helper for call_for_symbol_thunks_and_aliases. */
kono
parents:
diff changeset
924
kono
parents:
diff changeset
925 static bool
kono
parents:
diff changeset
926 set_local (cgraph_node *node, void *data)
kono
parents:
diff changeset
927 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
928 node->local = data != NULL;
111
kono
parents:
diff changeset
929 return false;
kono
parents:
diff changeset
930 }
kono
parents:
diff changeset
931
kono
parents:
diff changeset
932 /* TREE_ADDRESSABLE of NODE to true.
kono
parents:
diff changeset
933 Helper for call_for_symbol_thunks_and_aliases. */
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935 static bool
kono
parents:
diff changeset
936 set_addressable (varpool_node *node, void *)
kono
parents:
diff changeset
937 {
kono
parents:
diff changeset
938 TREE_ADDRESSABLE (node->decl) = 1;
kono
parents:
diff changeset
939 return false;
kono
parents:
diff changeset
940 }
kono
parents:
diff changeset
941
kono
parents:
diff changeset
942 /* Clear DECL_RTL of NODE.
kono
parents:
diff changeset
943 Helper for call_for_symbol_thunks_and_aliases. */
kono
parents:
diff changeset
944
kono
parents:
diff changeset
945 static bool
kono
parents:
diff changeset
946 clear_decl_rtl (symtab_node *node, void *)
kono
parents:
diff changeset
947 {
kono
parents:
diff changeset
948 SET_DECL_RTL (node->decl, NULL);
kono
parents:
diff changeset
949 return false;
kono
parents:
diff changeset
950 }
kono
parents:
diff changeset
951
kono
parents:
diff changeset
952 /* Redirect all callers of N and its aliases to TO. Remove aliases if
kono
parents:
diff changeset
953 possible. Return number of redirections made. */
kono
parents:
diff changeset
954
kono
parents:
diff changeset
955 static int
kono
parents:
diff changeset
956 redirect_all_callers (cgraph_node *n, cgraph_node *to)
kono
parents:
diff changeset
957 {
kono
parents:
diff changeset
958 int nredirected = 0;
kono
parents:
diff changeset
959 ipa_ref *ref;
kono
parents:
diff changeset
960 cgraph_edge *e = n->callers;
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 while (e)
kono
parents:
diff changeset
963 {
kono
parents:
diff changeset
964 /* Redirecting thunks to interposable symbols or symbols in other sections
kono
parents:
diff changeset
965 may not be supported by target output code. Play safe for now and
kono
parents:
diff changeset
966 punt on redirection. */
kono
parents:
diff changeset
967 if (!e->caller->thunk.thunk_p)
kono
parents:
diff changeset
968 {
kono
parents:
diff changeset
969 struct cgraph_edge *nexte = e->next_caller;
kono
parents:
diff changeset
970 e->redirect_callee (to);
kono
parents:
diff changeset
971 e = nexte;
kono
parents:
diff changeset
972 nredirected++;
kono
parents:
diff changeset
973 }
kono
parents:
diff changeset
974 else
kono
parents:
diff changeset
975 e = e->next_callee;
kono
parents:
diff changeset
976 }
kono
parents:
diff changeset
977 for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
kono
parents:
diff changeset
978 {
kono
parents:
diff changeset
979 bool removed = false;
kono
parents:
diff changeset
980 cgraph_node *n_alias = dyn_cast <cgraph_node *> (ref->referring);
kono
parents:
diff changeset
981
kono
parents:
diff changeset
982 if ((DECL_COMDAT_GROUP (n->decl)
kono
parents:
diff changeset
983 && (DECL_COMDAT_GROUP (n->decl)
kono
parents:
diff changeset
984 == DECL_COMDAT_GROUP (n_alias->decl)))
kono
parents:
diff changeset
985 || (n_alias->get_availability () > AVAIL_INTERPOSABLE
kono
parents:
diff changeset
986 && n->get_availability () > AVAIL_INTERPOSABLE))
kono
parents:
diff changeset
987 {
kono
parents:
diff changeset
988 nredirected += redirect_all_callers (n_alias, to);
kono
parents:
diff changeset
989 if (n_alias->can_remove_if_no_direct_calls_p ()
kono
parents:
diff changeset
990 && !n_alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
kono
parents:
diff changeset
991 NULL, true)
kono
parents:
diff changeset
992 && !n_alias->has_aliases_p ())
kono
parents:
diff changeset
993 n_alias->remove ();
kono
parents:
diff changeset
994 }
kono
parents:
diff changeset
995 if (!removed)
kono
parents:
diff changeset
996 i++;
kono
parents:
diff changeset
997 }
kono
parents:
diff changeset
998 return nredirected;
kono
parents:
diff changeset
999 }
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
kono
parents:
diff changeset
1002 be applied. */
kono
parents:
diff changeset
1003
kono
parents:
diff changeset
1004 bool
kono
parents:
diff changeset
1005 sem_function::merge (sem_item *alias_item)
kono
parents:
diff changeset
1006 {
kono
parents:
diff changeset
1007 gcc_assert (alias_item->type == FUNC);
kono
parents:
diff changeset
1008
kono
parents:
diff changeset
1009 sem_function *alias_func = static_cast<sem_function *> (alias_item);
kono
parents:
diff changeset
1010
kono
parents:
diff changeset
1011 cgraph_node *original = get_node ();
kono
parents:
diff changeset
1012 cgraph_node *local_original = NULL;
kono
parents:
diff changeset
1013 cgraph_node *alias = alias_func->get_node ();
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 bool create_wrapper = false;
kono
parents:
diff changeset
1016 bool create_alias = false;
kono
parents:
diff changeset
1017 bool redirect_callers = false;
kono
parents:
diff changeset
1018 bool remove = false;
kono
parents:
diff changeset
1019
kono
parents:
diff changeset
1020 bool original_discardable = false;
kono
parents:
diff changeset
1021 bool original_discarded = false;
kono
parents:
diff changeset
1022
kono
parents:
diff changeset
1023 bool original_address_matters = original->address_matters_p ();
kono
parents:
diff changeset
1024 bool alias_address_matters = alias->address_matters_p ();
kono
parents:
diff changeset
1025
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1026 AUTO_DUMP_SCOPE ("merge",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1027 dump_user_location_t::from_function_decl (decl));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1028
111
kono
parents:
diff changeset
1029 if (DECL_EXTERNAL (alias->decl))
kono
parents:
diff changeset
1030 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1031 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1032 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1033 "Not unifying; alias is external.\n");
111
kono
parents:
diff changeset
1034 return false;
kono
parents:
diff changeset
1035 }
kono
parents:
diff changeset
1036
kono
parents:
diff changeset
1037 if (DECL_NO_INLINE_WARNING_P (original->decl)
kono
parents:
diff changeset
1038 != DECL_NO_INLINE_WARNING_P (alias->decl))
kono
parents:
diff changeset
1039 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1040 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1041 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1042 "Not unifying; DECL_NO_INLINE_WARNING mismatch.\n");
111
kono
parents:
diff changeset
1043 return false;
kono
parents:
diff changeset
1044 }
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 /* Do not attempt to mix functions from different user sections;
kono
parents:
diff changeset
1047 we do not know what user intends with those. */
kono
parents:
diff changeset
1048 if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
kono
parents:
diff changeset
1049 || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
kono
parents:
diff changeset
1050 && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
kono
parents:
diff changeset
1051 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1052 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1053 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1054 "Not unifying; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1055 "original and alias are in different sections.\n");
111
kono
parents:
diff changeset
1056 return false;
kono
parents:
diff changeset
1057 }
kono
parents:
diff changeset
1058
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1059 if (!original->in_same_comdat_group_p (alias)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1060 || original->comdat_local_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1061 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1062 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1063 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1064 "Not unifying; alias nor wrapper cannot be created; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1065 "across comdat group boundary\n");
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1066 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1067 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1068
111
kono
parents:
diff changeset
1069 /* See if original is in a section that can be discarded if the main
kono
parents:
diff changeset
1070 symbol is not used. */
kono
parents:
diff changeset
1071
kono
parents:
diff changeset
1072 if (original->can_be_discarded_p ())
kono
parents:
diff changeset
1073 original_discardable = true;
kono
parents:
diff changeset
1074 /* Also consider case where we have resolution info and we know that
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1075 original's definition is not going to be used. In this case we cannot
111
kono
parents:
diff changeset
1076 create alias to original. */
kono
parents:
diff changeset
1077 if (node->resolution != LDPR_UNKNOWN
kono
parents:
diff changeset
1078 && !decl_binds_to_current_def_p (node->decl))
kono
parents:
diff changeset
1079 original_discardable = original_discarded = true;
kono
parents:
diff changeset
1080
kono
parents:
diff changeset
1081 /* Creating a symtab alias is the optimal way to merge.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1082 It however cannot be used in the following cases:
111
kono
parents:
diff changeset
1083
kono
parents:
diff changeset
1084 1) if ORIGINAL and ALIAS may be possibly compared for address equality.
kono
parents:
diff changeset
1085 2) if ORIGINAL is in a section that may be discarded by linker or if
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1086 it is an external functions where we cannot create an alias
111
kono
parents:
diff changeset
1087 (ORIGINAL_DISCARDABLE)
kono
parents:
diff changeset
1088 3) if target do not support symbol aliases.
kono
parents:
diff changeset
1089 4) original and alias lie in different comdat groups.
kono
parents:
diff changeset
1090
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1091 If we cannot produce alias, we will turn ALIAS into WRAPPER of ORIGINAL
111
kono
parents:
diff changeset
1092 and/or redirect all callers from ALIAS to ORIGINAL. */
kono
parents:
diff changeset
1093 if ((original_address_matters && alias_address_matters)
kono
parents:
diff changeset
1094 || (original_discardable
kono
parents:
diff changeset
1095 && (!DECL_COMDAT_GROUP (alias->decl)
kono
parents:
diff changeset
1096 || (DECL_COMDAT_GROUP (alias->decl)
kono
parents:
diff changeset
1097 != DECL_COMDAT_GROUP (original->decl))))
kono
parents:
diff changeset
1098 || original_discarded
kono
parents:
diff changeset
1099 || !sem_item::target_supports_symbol_aliases_p ()
kono
parents:
diff changeset
1100 || DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl))
kono
parents:
diff changeset
1101 {
kono
parents:
diff changeset
1102 /* First see if we can produce wrapper. */
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 /* Symbol properties that matter for references must be preserved.
kono
parents:
diff changeset
1105 TODO: We can produce wrapper, but we need to produce alias of ORIGINAL
kono
parents:
diff changeset
1106 with proper properties. */
kono
parents:
diff changeset
1107 if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
kono
parents:
diff changeset
1108 alias->address_taken))
kono
parents:
diff changeset
1109 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1110 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1111 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1112 "Wrapper cannot be created because referenced symbol "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1113 "properties mismatch\n");
111
kono
parents:
diff changeset
1114 }
kono
parents:
diff changeset
1115 /* Do not turn function in one comdat group into wrapper to another
kono
parents:
diff changeset
1116 comdat group. Other compiler producing the body of the
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1117 another comdat group may make opposite decision and with unfortunate
111
kono
parents:
diff changeset
1118 linker choices this may close a loop. */
kono
parents:
diff changeset
1119 else if (DECL_COMDAT_GROUP (original->decl)
kono
parents:
diff changeset
1120 && DECL_COMDAT_GROUP (alias->decl)
kono
parents:
diff changeset
1121 && (DECL_COMDAT_GROUP (alias->decl)
kono
parents:
diff changeset
1122 != DECL_COMDAT_GROUP (original->decl)))
kono
parents:
diff changeset
1123 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1124 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1125 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1126 "Wrapper cannot be created because of COMDAT\n");
111
kono
parents:
diff changeset
1127 }
kono
parents:
diff changeset
1128 else if (DECL_STATIC_CHAIN (alias->decl)
kono
parents:
diff changeset
1129 || DECL_STATIC_CHAIN (original->decl))
kono
parents:
diff changeset
1130 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1131 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1132 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1133 "Cannot create wrapper of nested function.\n");
111
kono
parents:
diff changeset
1134 }
kono
parents:
diff changeset
1135 /* TODO: We can also deal with variadic functions never calling
kono
parents:
diff changeset
1136 VA_START. */
kono
parents:
diff changeset
1137 else if (stdarg_p (TREE_TYPE (alias->decl)))
kono
parents:
diff changeset
1138 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1139 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1140 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1141 "cannot create wrapper of stdarg function.\n");
111
kono
parents:
diff changeset
1142 }
kono
parents:
diff changeset
1143 else if (ipa_fn_summaries
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1144 && ipa_size_summaries->get (alias) != NULL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1145 && ipa_size_summaries->get (alias)->self_size <= 2)
111
kono
parents:
diff changeset
1146 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1147 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1148 dump_printf (MSG_MISSED_OPTIMIZATION, "Wrapper creation is not "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1149 "profitable (function is too small).\n");
111
kono
parents:
diff changeset
1150 }
kono
parents:
diff changeset
1151 /* If user paid attention to mark function noinline, assume it is
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1152 somewhat special and do not try to turn it into a wrapper that
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1153 cannot be undone by inliner. */
111
kono
parents:
diff changeset
1154 else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (alias->decl)))
kono
parents:
diff changeset
1155 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1156 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1157 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1158 "Wrappers are not created for noinline.\n");
111
kono
parents:
diff changeset
1159 }
kono
parents:
diff changeset
1160 else
kono
parents:
diff changeset
1161 create_wrapper = true;
kono
parents:
diff changeset
1162
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1163 /* We can redirect local calls in the case both alias and original
111
kono
parents:
diff changeset
1164 are not interposable. */
kono
parents:
diff changeset
1165 redirect_callers
kono
parents:
diff changeset
1166 = alias->get_availability () > AVAIL_INTERPOSABLE
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1167 && original->get_availability () > AVAIL_INTERPOSABLE;
111
kono
parents:
diff changeset
1168 /* TODO: We can redirect, but we need to produce alias of ORIGINAL
kono
parents:
diff changeset
1169 with proper properties. */
kono
parents:
diff changeset
1170 if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
kono
parents:
diff changeset
1171 alias->address_taken))
kono
parents:
diff changeset
1172 redirect_callers = false;
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 if (!redirect_callers && !create_wrapper)
kono
parents:
diff changeset
1175 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1176 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1177 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1178 "Not unifying; cannot redirect callers nor "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1179 "produce wrapper\n");
111
kono
parents:
diff changeset
1180 return false;
kono
parents:
diff changeset
1181 }
kono
parents:
diff changeset
1182
kono
parents:
diff changeset
1183 /* Work out the symbol the wrapper should call.
kono
parents:
diff changeset
1184 If ORIGINAL is interposable, we need to call a local alias.
kono
parents:
diff changeset
1185 Also produce local alias (if possible) as an optimization.
kono
parents:
diff changeset
1186
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1187 Local aliases cannot be created inside comdat groups because that
111
kono
parents:
diff changeset
1188 prevents inlining. */
kono
parents:
diff changeset
1189 if (!original_discardable && !original->get_comdat_group ())
kono
parents:
diff changeset
1190 {
kono
parents:
diff changeset
1191 local_original
kono
parents:
diff changeset
1192 = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
kono
parents:
diff changeset
1193 if (!local_original
kono
parents:
diff changeset
1194 && original->get_availability () > AVAIL_INTERPOSABLE)
kono
parents:
diff changeset
1195 local_original = original;
kono
parents:
diff changeset
1196 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1197 /* If we cannot use local alias, fallback to the original
111
kono
parents:
diff changeset
1198 when possible. */
kono
parents:
diff changeset
1199 else if (original->get_availability () > AVAIL_INTERPOSABLE)
kono
parents:
diff changeset
1200 local_original = original;
kono
parents:
diff changeset
1201
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1202 /* If original is COMDAT local, we cannot really redirect calls outside
111
kono
parents:
diff changeset
1203 of its comdat group to it. */
kono
parents:
diff changeset
1204 if (original->comdat_local_p ())
kono
parents:
diff changeset
1205 redirect_callers = false;
kono
parents:
diff changeset
1206 if (!local_original)
kono
parents:
diff changeset
1207 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1208 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1209 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1210 "Not unifying; cannot produce local alias.\n");
111
kono
parents:
diff changeset
1211 return false;
kono
parents:
diff changeset
1212 }
kono
parents:
diff changeset
1213
kono
parents:
diff changeset
1214 if (!redirect_callers && !create_wrapper)
kono
parents:
diff changeset
1215 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1216 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1217 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1218 "Not unifying; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1219 "cannot redirect callers nor produce a wrapper\n");
111
kono
parents:
diff changeset
1220 return false;
kono
parents:
diff changeset
1221 }
kono
parents:
diff changeset
1222 if (!create_wrapper
kono
parents:
diff changeset
1223 && !alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
kono
parents:
diff changeset
1224 NULL, true)
kono
parents:
diff changeset
1225 && !alias->can_remove_if_no_direct_calls_p ())
kono
parents:
diff changeset
1226 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1227 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1228 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1229 "Not unifying; cannot make wrapper and "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1230 "function has other uses than direct calls\n");
111
kono
parents:
diff changeset
1231 return false;
kono
parents:
diff changeset
1232 }
kono
parents:
diff changeset
1233 }
kono
parents:
diff changeset
1234 else
kono
parents:
diff changeset
1235 create_alias = true;
kono
parents:
diff changeset
1236
kono
parents:
diff changeset
1237 if (redirect_callers)
kono
parents:
diff changeset
1238 {
kono
parents:
diff changeset
1239 int nredirected = redirect_all_callers (alias, local_original);
kono
parents:
diff changeset
1240
kono
parents:
diff changeset
1241 if (nredirected)
kono
parents:
diff changeset
1242 {
kono
parents:
diff changeset
1243 alias->icf_merged = true;
kono
parents:
diff changeset
1244 local_original->icf_merged = true;
kono
parents:
diff changeset
1245
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1246 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1247 dump_printf (MSG_NOTE,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1248 "%i local calls have been "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1249 "redirected.\n", nredirected);
111
kono
parents:
diff changeset
1250 }
kono
parents:
diff changeset
1251
kono
parents:
diff changeset
1252 /* If all callers was redirected, do not produce wrapper. */
kono
parents:
diff changeset
1253 if (alias->can_remove_if_no_direct_calls_p ()
kono
parents:
diff changeset
1254 && !DECL_VIRTUAL_P (alias->decl)
kono
parents:
diff changeset
1255 && !alias->has_aliases_p ())
kono
parents:
diff changeset
1256 {
kono
parents:
diff changeset
1257 create_wrapper = false;
kono
parents:
diff changeset
1258 remove = true;
kono
parents:
diff changeset
1259 }
kono
parents:
diff changeset
1260 gcc_assert (!create_alias);
kono
parents:
diff changeset
1261 }
kono
parents:
diff changeset
1262 else if (create_alias)
kono
parents:
diff changeset
1263 {
kono
parents:
diff changeset
1264 alias->icf_merged = true;
kono
parents:
diff changeset
1265
kono
parents:
diff changeset
1266 /* Remove the function's body. */
kono
parents:
diff changeset
1267 ipa_merge_profiles (original, alias);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1268 symtab->call_cgraph_removal_hooks (alias);
111
kono
parents:
diff changeset
1269 alias->release_body (true);
kono
parents:
diff changeset
1270 alias->reset ();
kono
parents:
diff changeset
1271 /* Notice global symbol possibly produced RTL. */
kono
parents:
diff changeset
1272 ((symtab_node *)alias)->call_for_symbol_and_aliases (clear_decl_rtl,
kono
parents:
diff changeset
1273 NULL, true);
kono
parents:
diff changeset
1274
kono
parents:
diff changeset
1275 /* Create the alias. */
kono
parents:
diff changeset
1276 cgraph_node::create_alias (alias_func->decl, decl);
kono
parents:
diff changeset
1277 alias->resolve_alias (original);
kono
parents:
diff changeset
1278
kono
parents:
diff changeset
1279 original->call_for_symbol_thunks_and_aliases
kono
parents:
diff changeset
1280 (set_local, (void *)(size_t) original->local_p (), true);
kono
parents:
diff changeset
1281
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1282 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1283 dump_printf (MSG_OPTIMIZED_LOCATIONS,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1284 "Unified; Function alias has been created.\n");
111
kono
parents:
diff changeset
1285 }
kono
parents:
diff changeset
1286 if (create_wrapper)
kono
parents:
diff changeset
1287 {
kono
parents:
diff changeset
1288 gcc_assert (!create_alias);
kono
parents:
diff changeset
1289 alias->icf_merged = true;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1290 symtab->call_cgraph_removal_hooks (alias);
111
kono
parents:
diff changeset
1291 local_original->icf_merged = true;
kono
parents:
diff changeset
1292
kono
parents:
diff changeset
1293 /* FIXME update local_original counts. */
kono
parents:
diff changeset
1294 ipa_merge_profiles (original, alias, true);
kono
parents:
diff changeset
1295 alias->create_wrapper (local_original);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1296 symtab->call_cgraph_insertion_hooks (alias);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1297
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1298 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1299 dump_printf (MSG_OPTIMIZED_LOCATIONS,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1300 "Unified; Wrapper has been created.\n");
111
kono
parents:
diff changeset
1301 }
kono
parents:
diff changeset
1302
kono
parents:
diff changeset
1303 /* It's possible that redirection can hit thunks that block
kono
parents:
diff changeset
1304 redirection opportunities. */
kono
parents:
diff changeset
1305 gcc_assert (alias->icf_merged || remove || redirect_callers);
kono
parents:
diff changeset
1306 original->icf_merged = true;
kono
parents:
diff changeset
1307
kono
parents:
diff changeset
1308 /* We use merged flag to track cases where COMDAT function is known to be
kono
parents:
diff changeset
1309 compatible its callers. If we merged in non-COMDAT, we need to give up
kono
parents:
diff changeset
1310 on this optimization. */
kono
parents:
diff changeset
1311 if (original->merged_comdat && !alias->merged_comdat)
kono
parents:
diff changeset
1312 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1313 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1314 dump_printf (MSG_NOTE, "Dropping merged_comdat flag.\n");
111
kono
parents:
diff changeset
1315 if (local_original)
kono
parents:
diff changeset
1316 local_original->merged_comdat = false;
kono
parents:
diff changeset
1317 original->merged_comdat = false;
kono
parents:
diff changeset
1318 }
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 if (remove)
kono
parents:
diff changeset
1321 {
kono
parents:
diff changeset
1322 ipa_merge_profiles (original, alias);
kono
parents:
diff changeset
1323 alias->release_body ();
kono
parents:
diff changeset
1324 alias->reset ();
kono
parents:
diff changeset
1325 alias->body_removed = true;
kono
parents:
diff changeset
1326 alias->icf_merged = true;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1327 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1328 dump_printf (MSG_OPTIMIZED_LOCATIONS,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1329 "Unified; Function body was removed.\n");
111
kono
parents:
diff changeset
1330 }
kono
parents:
diff changeset
1331
kono
parents:
diff changeset
1332 return true;
kono
parents:
diff changeset
1333 }
kono
parents:
diff changeset
1334
kono
parents:
diff changeset
1335 /* Semantic item initialization function. */
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1338 sem_function::init (ipa_icf_gimple::func_checker *checker)
111
kono
parents:
diff changeset
1339 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1340 m_checker = checker;
111
kono
parents:
diff changeset
1341 if (in_lto_p)
kono
parents:
diff changeset
1342 get_node ()->get_untransformed_body ();
kono
parents:
diff changeset
1343
kono
parents:
diff changeset
1344 tree fndecl = node->decl;
kono
parents:
diff changeset
1345 function *func = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
1346
kono
parents:
diff changeset
1347 gcc_assert (func);
kono
parents:
diff changeset
1348 gcc_assert (SSANAMES (func));
kono
parents:
diff changeset
1349
kono
parents:
diff changeset
1350 ssa_names_size = SSANAMES (func)->length ();
kono
parents:
diff changeset
1351 node = node;
kono
parents:
diff changeset
1352
kono
parents:
diff changeset
1353 decl = fndecl;
kono
parents:
diff changeset
1354 region_tree = func->eh->region_tree;
kono
parents:
diff changeset
1355
kono
parents:
diff changeset
1356 /* iterating all function arguments. */
kono
parents:
diff changeset
1357 arg_count = count_formal_params (fndecl);
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 edge_count = n_edges_for_fn (func);
kono
parents:
diff changeset
1360 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
kono
parents:
diff changeset
1361 if (!cnode->thunk.thunk_p)
kono
parents:
diff changeset
1362 {
kono
parents:
diff changeset
1363 cfg_checksum = coverage_compute_cfg_checksum (func);
kono
parents:
diff changeset
1364
kono
parents:
diff changeset
1365 inchash::hash hstate;
kono
parents:
diff changeset
1366
kono
parents:
diff changeset
1367 basic_block bb;
kono
parents:
diff changeset
1368 FOR_EACH_BB_FN (bb, func)
kono
parents:
diff changeset
1369 {
kono
parents:
diff changeset
1370 unsigned nondbg_stmt_count = 0;
kono
parents:
diff changeset
1371
kono
parents:
diff changeset
1372 edge e;
kono
parents:
diff changeset
1373 for (edge_iterator ei = ei_start (bb->preds); ei_cond (ei, &e);
kono
parents:
diff changeset
1374 ei_next (&ei))
kono
parents:
diff changeset
1375 cfg_checksum = iterative_hash_host_wide_int (e->flags,
kono
parents:
diff changeset
1376 cfg_checksum);
kono
parents:
diff changeset
1377
kono
parents:
diff changeset
1378 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
kono
parents:
diff changeset
1379 gsi_next (&gsi))
kono
parents:
diff changeset
1380 {
kono
parents:
diff changeset
1381 gimple *stmt = gsi_stmt (gsi);
kono
parents:
diff changeset
1382
kono
parents:
diff changeset
1383 if (gimple_code (stmt) != GIMPLE_DEBUG
kono
parents:
diff changeset
1384 && gimple_code (stmt) != GIMPLE_PREDICT)
kono
parents:
diff changeset
1385 {
kono
parents:
diff changeset
1386 hash_stmt (stmt, hstate);
kono
parents:
diff changeset
1387 nondbg_stmt_count++;
kono
parents:
diff changeset
1388 }
kono
parents:
diff changeset
1389 }
kono
parents:
diff changeset
1390
kono
parents:
diff changeset
1391 hstate.commit_flag ();
kono
parents:
diff changeset
1392 gcode_hash = hstate.end ();
kono
parents:
diff changeset
1393 bb_sizes.safe_push (nondbg_stmt_count);
kono
parents:
diff changeset
1394
kono
parents:
diff changeset
1395 /* Inserting basic block to hash table. */
kono
parents:
diff changeset
1396 sem_bb *semantic_bb = new sem_bb (bb, nondbg_stmt_count,
kono
parents:
diff changeset
1397 EDGE_COUNT (bb->preds)
kono
parents:
diff changeset
1398 + EDGE_COUNT (bb->succs));
kono
parents:
diff changeset
1399
kono
parents:
diff changeset
1400 bb_sorted.safe_push (semantic_bb);
kono
parents:
diff changeset
1401 }
kono
parents:
diff changeset
1402 }
kono
parents:
diff changeset
1403 else
kono
parents:
diff changeset
1404 {
kono
parents:
diff changeset
1405 cfg_checksum = 0;
kono
parents:
diff changeset
1406 inchash::hash hstate;
kono
parents:
diff changeset
1407 hstate.add_hwi (cnode->thunk.fixed_offset);
kono
parents:
diff changeset
1408 hstate.add_hwi (cnode->thunk.virtual_value);
kono
parents:
diff changeset
1409 hstate.add_flag (cnode->thunk.this_adjusting);
kono
parents:
diff changeset
1410 hstate.add_flag (cnode->thunk.virtual_offset_p);
kono
parents:
diff changeset
1411 gcode_hash = hstate.end ();
kono
parents:
diff changeset
1412 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1413
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1414 m_checker = NULL;
111
kono
parents:
diff changeset
1415 }
kono
parents:
diff changeset
1416
kono
parents:
diff changeset
1417 /* Improve accumulated hash for HSTATE based on a gimple statement STMT. */
kono
parents:
diff changeset
1418
kono
parents:
diff changeset
1419 void
kono
parents:
diff changeset
1420 sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
kono
parents:
diff changeset
1421 {
kono
parents:
diff changeset
1422 enum gimple_code code = gimple_code (stmt);
kono
parents:
diff changeset
1423
kono
parents:
diff changeset
1424 hstate.add_int (code);
kono
parents:
diff changeset
1425
kono
parents:
diff changeset
1426 switch (code)
kono
parents:
diff changeset
1427 {
kono
parents:
diff changeset
1428 case GIMPLE_SWITCH:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1429 m_checker->hash_operand (gimple_switch_index (as_a <gswitch *> (stmt)),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1430 hstate, 0);
111
kono
parents:
diff changeset
1431 break;
kono
parents:
diff changeset
1432 case GIMPLE_ASSIGN:
kono
parents:
diff changeset
1433 hstate.add_int (gimple_assign_rhs_code (stmt));
kono
parents:
diff changeset
1434 if (commutative_tree_code (gimple_assign_rhs_code (stmt))
kono
parents:
diff changeset
1435 || commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
kono
parents:
diff changeset
1436 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1437 m_checker->hash_operand (gimple_assign_rhs1 (stmt), hstate, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1438 m_checker->hash_operand (gimple_assign_rhs2 (stmt), hstate, 0);
111
kono
parents:
diff changeset
1439 if (commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1440 m_checker->hash_operand (gimple_assign_rhs3 (stmt), hstate, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1441 m_checker->hash_operand (gimple_assign_lhs (stmt), hstate, 0);
111
kono
parents:
diff changeset
1442 }
kono
parents:
diff changeset
1443 /* fall through */
kono
parents:
diff changeset
1444 case GIMPLE_CALL:
kono
parents:
diff changeset
1445 case GIMPLE_ASM:
kono
parents:
diff changeset
1446 case GIMPLE_COND:
kono
parents:
diff changeset
1447 case GIMPLE_GOTO:
kono
parents:
diff changeset
1448 case GIMPLE_RETURN:
kono
parents:
diff changeset
1449 /* All these statements are equivalent if their operands are. */
kono
parents:
diff changeset
1450 for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1451 m_checker->hash_operand (gimple_op (stmt, i), hstate, 0);
111
kono
parents:
diff changeset
1452 /* Consider nocf_check attribute in hash as it affects code
kono
parents:
diff changeset
1453 generation. */
kono
parents:
diff changeset
1454 if (code == GIMPLE_CALL
kono
parents:
diff changeset
1455 && flag_cf_protection & CF_BRANCH)
kono
parents:
diff changeset
1456 hstate.add_flag (gimple_call_nocf_check_p (as_a <gcall *> (stmt)));
kono
parents:
diff changeset
1457 default:
kono
parents:
diff changeset
1458 break;
kono
parents:
diff changeset
1459 }
kono
parents:
diff changeset
1460 }
kono
parents:
diff changeset
1461
kono
parents:
diff changeset
1462
kono
parents:
diff changeset
1463 /* Return true if polymorphic comparison must be processed. */
kono
parents:
diff changeset
1464
kono
parents:
diff changeset
1465 bool
kono
parents:
diff changeset
1466 sem_function::compare_polymorphic_p (void)
kono
parents:
diff changeset
1467 {
kono
parents:
diff changeset
1468 struct cgraph_edge *e;
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 if (!opt_for_fn (get_node ()->decl, flag_devirtualize))
kono
parents:
diff changeset
1471 return false;
kono
parents:
diff changeset
1472 if (get_node ()->indirect_calls != NULL)
kono
parents:
diff changeset
1473 return true;
kono
parents:
diff changeset
1474 /* TODO: We can do simple propagation determining what calls may lead to
kono
parents:
diff changeset
1475 a polymorphic call. */
kono
parents:
diff changeset
1476 for (e = get_node ()->callees; e; e = e->next_callee)
kono
parents:
diff changeset
1477 if (e->callee->definition
kono
parents:
diff changeset
1478 && opt_for_fn (e->callee->decl, flag_devirtualize))
kono
parents:
diff changeset
1479 return true;
kono
parents:
diff changeset
1480 return false;
kono
parents:
diff changeset
1481 }
kono
parents:
diff changeset
1482
kono
parents:
diff changeset
1483 /* For a given call graph NODE, the function constructs new
kono
parents:
diff changeset
1484 semantic function item. */
kono
parents:
diff changeset
1485
kono
parents:
diff changeset
1486 sem_function *
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1487 sem_function::parse (cgraph_node *node, bitmap_obstack *stack,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1488 func_checker *checker)
111
kono
parents:
diff changeset
1489 {
kono
parents:
diff changeset
1490 tree fndecl = node->decl;
kono
parents:
diff changeset
1491 function *func = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493 if (!func || (!node->has_gimple_body_p () && !node->thunk.thunk_p))
kono
parents:
diff changeset
1494 return NULL;
kono
parents:
diff changeset
1495
kono
parents:
diff changeset
1496 if (lookup_attribute_by_prefix ("omp ", DECL_ATTRIBUTES (node->decl)) != NULL)
kono
parents:
diff changeset
1497 return NULL;
kono
parents:
diff changeset
1498
kono
parents:
diff changeset
1499 if (lookup_attribute_by_prefix ("oacc ",
kono
parents:
diff changeset
1500 DECL_ATTRIBUTES (node->decl)) != NULL)
kono
parents:
diff changeset
1501 return NULL;
kono
parents:
diff changeset
1502
kono
parents:
diff changeset
1503 /* PR ipa/70306. */
kono
parents:
diff changeset
1504 if (DECL_STATIC_CONSTRUCTOR (node->decl)
kono
parents:
diff changeset
1505 || DECL_STATIC_DESTRUCTOR (node->decl))
kono
parents:
diff changeset
1506 return NULL;
kono
parents:
diff changeset
1507
kono
parents:
diff changeset
1508 sem_function *f = new sem_function (node, stack);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1509 f->init (checker);
111
kono
parents:
diff changeset
1510
kono
parents:
diff changeset
1511 return f;
kono
parents:
diff changeset
1512 }
kono
parents:
diff changeset
1513
kono
parents:
diff changeset
1514 /* For given basic blocks BB1 and BB2 (from functions FUNC1 and FUNC),
kono
parents:
diff changeset
1515 return true if phi nodes are semantically equivalent in these blocks . */
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517 bool
kono
parents:
diff changeset
1518 sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
kono
parents:
diff changeset
1519 {
kono
parents:
diff changeset
1520 gphi_iterator si1, si2;
kono
parents:
diff changeset
1521 gphi *phi1, *phi2;
kono
parents:
diff changeset
1522 unsigned size1, size2, i;
kono
parents:
diff changeset
1523 tree t1, t2;
kono
parents:
diff changeset
1524 edge e1, e2;
kono
parents:
diff changeset
1525
kono
parents:
diff changeset
1526 gcc_assert (bb1 != NULL);
kono
parents:
diff changeset
1527 gcc_assert (bb2 != NULL);
kono
parents:
diff changeset
1528
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1529 si2 = gsi_start_nonvirtual_phis (bb2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1530 for (si1 = gsi_start_nonvirtual_phis (bb1); !gsi_end_p (si1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1531 gsi_next_nonvirtual_phi (&si1))
111
kono
parents:
diff changeset
1532 {
kono
parents:
diff changeset
1533 if (gsi_end_p (si1) && gsi_end_p (si2))
kono
parents:
diff changeset
1534 break;
kono
parents:
diff changeset
1535
kono
parents:
diff changeset
1536 if (gsi_end_p (si1) || gsi_end_p (si2))
kono
parents:
diff changeset
1537 return return_false();
kono
parents:
diff changeset
1538
kono
parents:
diff changeset
1539 phi1 = si1.phi ();
kono
parents:
diff changeset
1540 phi2 = si2.phi ();
kono
parents:
diff changeset
1541
kono
parents:
diff changeset
1542 tree phi_result1 = gimple_phi_result (phi1);
kono
parents:
diff changeset
1543 tree phi_result2 = gimple_phi_result (phi2);
kono
parents:
diff changeset
1544
kono
parents:
diff changeset
1545 if (!m_checker->compare_operand (phi_result1, phi_result2))
kono
parents:
diff changeset
1546 return return_false_with_msg ("PHI results are different");
kono
parents:
diff changeset
1547
kono
parents:
diff changeset
1548 size1 = gimple_phi_num_args (phi1);
kono
parents:
diff changeset
1549 size2 = gimple_phi_num_args (phi2);
kono
parents:
diff changeset
1550
kono
parents:
diff changeset
1551 if (size1 != size2)
kono
parents:
diff changeset
1552 return return_false ();
kono
parents:
diff changeset
1553
kono
parents:
diff changeset
1554 for (i = 0; i < size1; ++i)
kono
parents:
diff changeset
1555 {
kono
parents:
diff changeset
1556 t1 = gimple_phi_arg (phi1, i)->def;
kono
parents:
diff changeset
1557 t2 = gimple_phi_arg (phi2, i)->def;
kono
parents:
diff changeset
1558
kono
parents:
diff changeset
1559 if (!m_checker->compare_operand (t1, t2))
kono
parents:
diff changeset
1560 return return_false ();
kono
parents:
diff changeset
1561
kono
parents:
diff changeset
1562 e1 = gimple_phi_arg_edge (phi1, i);
kono
parents:
diff changeset
1563 e2 = gimple_phi_arg_edge (phi2, i);
kono
parents:
diff changeset
1564
kono
parents:
diff changeset
1565 if (!m_checker->compare_edge (e1, e2))
kono
parents:
diff changeset
1566 return return_false ();
kono
parents:
diff changeset
1567 }
kono
parents:
diff changeset
1568
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1569 gsi_next_nonvirtual_phi (&si2);
111
kono
parents:
diff changeset
1570 }
kono
parents:
diff changeset
1571
kono
parents:
diff changeset
1572 return true;
kono
parents:
diff changeset
1573 }
kono
parents:
diff changeset
1574
kono
parents:
diff changeset
1575 /* Basic blocks dictionary BB_DICT returns true if SOURCE index BB
kono
parents:
diff changeset
1576 corresponds to TARGET. */
kono
parents:
diff changeset
1577
kono
parents:
diff changeset
1578 bool
kono
parents:
diff changeset
1579 sem_function::bb_dict_test (vec<int> *bb_dict, int source, int target)
kono
parents:
diff changeset
1580 {
kono
parents:
diff changeset
1581 source++;
kono
parents:
diff changeset
1582 target++;
kono
parents:
diff changeset
1583
kono
parents:
diff changeset
1584 if (bb_dict->length () <= (unsigned)source)
kono
parents:
diff changeset
1585 bb_dict->safe_grow_cleared (source + 1);
kono
parents:
diff changeset
1586
kono
parents:
diff changeset
1587 if ((*bb_dict)[source] == 0)
kono
parents:
diff changeset
1588 {
kono
parents:
diff changeset
1589 (*bb_dict)[source] = target;
kono
parents:
diff changeset
1590 return true;
kono
parents:
diff changeset
1591 }
kono
parents:
diff changeset
1592 else
kono
parents:
diff changeset
1593 return (*bb_dict)[source] == target;
kono
parents:
diff changeset
1594 }
kono
parents:
diff changeset
1595
kono
parents:
diff changeset
1596 sem_variable::sem_variable (bitmap_obstack *stack): sem_item (VAR, stack)
kono
parents:
diff changeset
1597 {
kono
parents:
diff changeset
1598 }
kono
parents:
diff changeset
1599
kono
parents:
diff changeset
1600 sem_variable::sem_variable (varpool_node *node, bitmap_obstack *stack)
kono
parents:
diff changeset
1601 : sem_item (VAR, node, stack)
kono
parents:
diff changeset
1602 {
kono
parents:
diff changeset
1603 gcc_checking_assert (node);
kono
parents:
diff changeset
1604 gcc_checking_assert (get_node ());
kono
parents:
diff changeset
1605 }
kono
parents:
diff changeset
1606
kono
parents:
diff changeset
1607 /* Fast equality function based on knowledge known in WPA. */
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 bool
kono
parents:
diff changeset
1610 sem_variable::equals_wpa (sem_item *item,
kono
parents:
diff changeset
1611 hash_map <symtab_node *, sem_item *> &ignored_nodes)
kono
parents:
diff changeset
1612 {
kono
parents:
diff changeset
1613 gcc_assert (item->type == VAR);
kono
parents:
diff changeset
1614
kono
parents:
diff changeset
1615 if (node->num_references () != item->node->num_references ())
kono
parents:
diff changeset
1616 return return_false_with_msg ("different number of references");
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 if (DECL_TLS_MODEL (decl) || DECL_TLS_MODEL (item->decl))
kono
parents:
diff changeset
1619 return return_false_with_msg ("TLS model");
kono
parents:
diff changeset
1620
kono
parents:
diff changeset
1621 /* DECL_ALIGN is safe to merge, because we will always chose the largest
kono
parents:
diff changeset
1622 alignment out of all aliases. */
kono
parents:
diff changeset
1623
kono
parents:
diff changeset
1624 if (DECL_VIRTUAL_P (decl) != DECL_VIRTUAL_P (item->decl))
kono
parents:
diff changeset
1625 return return_false_with_msg ("Virtual flag mismatch");
kono
parents:
diff changeset
1626
kono
parents:
diff changeset
1627 if (DECL_SIZE (decl) != DECL_SIZE (item->decl)
kono
parents:
diff changeset
1628 && ((!DECL_SIZE (decl) || !DECL_SIZE (item->decl))
kono
parents:
diff changeset
1629 || !operand_equal_p (DECL_SIZE (decl),
kono
parents:
diff changeset
1630 DECL_SIZE (item->decl), OEP_ONLY_CONST)))
kono
parents:
diff changeset
1631 return return_false_with_msg ("size mismatch");
kono
parents:
diff changeset
1632
kono
parents:
diff changeset
1633 /* Do not attempt to mix data from different user sections;
kono
parents:
diff changeset
1634 we do not know what user intends with those. */
kono
parents:
diff changeset
1635 if (((DECL_SECTION_NAME (decl) && !node->implicit_section)
kono
parents:
diff changeset
1636 || (DECL_SECTION_NAME (item->decl) && !item->node->implicit_section))
kono
parents:
diff changeset
1637 && DECL_SECTION_NAME (decl) != DECL_SECTION_NAME (item->decl))
kono
parents:
diff changeset
1638 return return_false_with_msg ("user section mismatch");
kono
parents:
diff changeset
1639
kono
parents:
diff changeset
1640 if (DECL_IN_TEXT_SECTION (decl) != DECL_IN_TEXT_SECTION (item->decl))
kono
parents:
diff changeset
1641 return return_false_with_msg ("text section");
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 ipa_ref *ref = NULL, *ref2 = NULL;
kono
parents:
diff changeset
1644 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
kono
parents:
diff changeset
1645 {
kono
parents:
diff changeset
1646 item->node->iterate_reference (i, ref2);
kono
parents:
diff changeset
1647
kono
parents:
diff changeset
1648 if (ref->use != ref2->use)
kono
parents:
diff changeset
1649 return return_false_with_msg ("reference use mismatch");
kono
parents:
diff changeset
1650
kono
parents:
diff changeset
1651 if (!compare_symbol_references (ignored_nodes,
kono
parents:
diff changeset
1652 ref->referred, ref2->referred,
kono
parents:
diff changeset
1653 ref->address_matters_p ()))
kono
parents:
diff changeset
1654 return false;
kono
parents:
diff changeset
1655 }
kono
parents:
diff changeset
1656
kono
parents:
diff changeset
1657 return true;
kono
parents:
diff changeset
1658 }
kono
parents:
diff changeset
1659
kono
parents:
diff changeset
1660 /* Returns true if the item equals to ITEM given as argument. */
kono
parents:
diff changeset
1661
kono
parents:
diff changeset
1662 bool
kono
parents:
diff changeset
1663 sem_variable::equals (sem_item *item,
kono
parents:
diff changeset
1664 hash_map <symtab_node *, sem_item *> &)
kono
parents:
diff changeset
1665 {
kono
parents:
diff changeset
1666 gcc_assert (item->type == VAR);
kono
parents:
diff changeset
1667 bool ret;
kono
parents:
diff changeset
1668
kono
parents:
diff changeset
1669 if (DECL_INITIAL (decl) == error_mark_node && in_lto_p)
kono
parents:
diff changeset
1670 dyn_cast <varpool_node *>(node)->get_constructor ();
kono
parents:
diff changeset
1671 if (DECL_INITIAL (item->decl) == error_mark_node && in_lto_p)
kono
parents:
diff changeset
1672 dyn_cast <varpool_node *>(item->node)->get_constructor ();
kono
parents:
diff changeset
1673
kono
parents:
diff changeset
1674 /* As seen in PR ipa/65303 we have to compare variables types. */
kono
parents:
diff changeset
1675 if (!func_checker::compatible_types_p (TREE_TYPE (decl),
kono
parents:
diff changeset
1676 TREE_TYPE (item->decl)))
kono
parents:
diff changeset
1677 return return_false_with_msg ("variables types are different");
kono
parents:
diff changeset
1678
kono
parents:
diff changeset
1679 ret = sem_variable::equals (DECL_INITIAL (decl),
kono
parents:
diff changeset
1680 DECL_INITIAL (item->node->decl));
kono
parents:
diff changeset
1681 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1682 fprintf (dump_file,
kono
parents:
diff changeset
1683 "Equals called for vars: %s:%s with result: %s\n\n",
kono
parents:
diff changeset
1684 node->dump_name (), item->node->dump_name (),
kono
parents:
diff changeset
1685 ret ? "true" : "false");
kono
parents:
diff changeset
1686
kono
parents:
diff changeset
1687 return ret;
kono
parents:
diff changeset
1688 }
kono
parents:
diff changeset
1689
kono
parents:
diff changeset
1690 /* Compares trees T1 and T2 for semantic equality. */
kono
parents:
diff changeset
1691
kono
parents:
diff changeset
1692 bool
kono
parents:
diff changeset
1693 sem_variable::equals (tree t1, tree t2)
kono
parents:
diff changeset
1694 {
kono
parents:
diff changeset
1695 if (!t1 || !t2)
kono
parents:
diff changeset
1696 return return_with_debug (t1 == t2);
kono
parents:
diff changeset
1697 if (t1 == t2)
kono
parents:
diff changeset
1698 return true;
kono
parents:
diff changeset
1699 tree_code tc1 = TREE_CODE (t1);
kono
parents:
diff changeset
1700 tree_code tc2 = TREE_CODE (t2);
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 if (tc1 != tc2)
kono
parents:
diff changeset
1703 return return_false_with_msg ("TREE_CODE mismatch");
kono
parents:
diff changeset
1704
kono
parents:
diff changeset
1705 switch (tc1)
kono
parents:
diff changeset
1706 {
kono
parents:
diff changeset
1707 case CONSTRUCTOR:
kono
parents:
diff changeset
1708 {
kono
parents:
diff changeset
1709 vec<constructor_elt, va_gc> *v1, *v2;
kono
parents:
diff changeset
1710 unsigned HOST_WIDE_INT idx;
kono
parents:
diff changeset
1711
kono
parents:
diff changeset
1712 enum tree_code typecode = TREE_CODE (TREE_TYPE (t1));
kono
parents:
diff changeset
1713 if (typecode != TREE_CODE (TREE_TYPE (t2)))
kono
parents:
diff changeset
1714 return return_false_with_msg ("constructor type mismatch");
kono
parents:
diff changeset
1715
kono
parents:
diff changeset
1716 if (typecode == ARRAY_TYPE)
kono
parents:
diff changeset
1717 {
kono
parents:
diff changeset
1718 HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
kono
parents:
diff changeset
1719 /* For arrays, check that the sizes all match. */
kono
parents:
diff changeset
1720 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
kono
parents:
diff changeset
1721 || size_1 == -1
kono
parents:
diff changeset
1722 || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
kono
parents:
diff changeset
1723 return return_false_with_msg ("constructor array size mismatch");
kono
parents:
diff changeset
1724 }
kono
parents:
diff changeset
1725 else if (!func_checker::compatible_types_p (TREE_TYPE (t1),
kono
parents:
diff changeset
1726 TREE_TYPE (t2)))
kono
parents:
diff changeset
1727 return return_false_with_msg ("constructor type incompatible");
kono
parents:
diff changeset
1728
kono
parents:
diff changeset
1729 v1 = CONSTRUCTOR_ELTS (t1);
kono
parents:
diff changeset
1730 v2 = CONSTRUCTOR_ELTS (t2);
kono
parents:
diff changeset
1731 if (vec_safe_length (v1) != vec_safe_length (v2))
kono
parents:
diff changeset
1732 return return_false_with_msg ("constructor number of elts mismatch");
kono
parents:
diff changeset
1733
kono
parents:
diff changeset
1734 for (idx = 0; idx < vec_safe_length (v1); ++idx)
kono
parents:
diff changeset
1735 {
kono
parents:
diff changeset
1736 constructor_elt *c1 = &(*v1)[idx];
kono
parents:
diff changeset
1737 constructor_elt *c2 = &(*v2)[idx];
kono
parents:
diff changeset
1738
kono
parents:
diff changeset
1739 /* Check that each value is the same... */
kono
parents:
diff changeset
1740 if (!sem_variable::equals (c1->value, c2->value))
kono
parents:
diff changeset
1741 return false;
kono
parents:
diff changeset
1742 /* ... and that they apply to the same fields! */
kono
parents:
diff changeset
1743 if (!sem_variable::equals (c1->index, c2->index))
kono
parents:
diff changeset
1744 return false;
kono
parents:
diff changeset
1745 }
kono
parents:
diff changeset
1746 return true;
kono
parents:
diff changeset
1747 }
kono
parents:
diff changeset
1748 case MEM_REF:
kono
parents:
diff changeset
1749 {
kono
parents:
diff changeset
1750 tree x1 = TREE_OPERAND (t1, 0);
kono
parents:
diff changeset
1751 tree x2 = TREE_OPERAND (t2, 0);
kono
parents:
diff changeset
1752 tree y1 = TREE_OPERAND (t1, 1);
kono
parents:
diff changeset
1753 tree y2 = TREE_OPERAND (t2, 1);
kono
parents:
diff changeset
1754
kono
parents:
diff changeset
1755 if (!func_checker::compatible_types_p (TREE_TYPE (x1), TREE_TYPE (x2)))
kono
parents:
diff changeset
1756 return return_false ();
kono
parents:
diff changeset
1757
kono
parents:
diff changeset
1758 /* Type of the offset on MEM_REF does not matter. */
kono
parents:
diff changeset
1759 return return_with_debug (sem_variable::equals (x1, x2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1760 && known_eq (wi::to_poly_offset (y1),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1761 wi::to_poly_offset (y2)));
111
kono
parents:
diff changeset
1762 }
kono
parents:
diff changeset
1763 case ADDR_EXPR:
kono
parents:
diff changeset
1764 case FDESC_EXPR:
kono
parents:
diff changeset
1765 {
kono
parents:
diff changeset
1766 tree op1 = TREE_OPERAND (t1, 0);
kono
parents:
diff changeset
1767 tree op2 = TREE_OPERAND (t2, 0);
kono
parents:
diff changeset
1768 return sem_variable::equals (op1, op2);
kono
parents:
diff changeset
1769 }
kono
parents:
diff changeset
1770 /* References to other vars/decls are compared using ipa-ref. */
kono
parents:
diff changeset
1771 case FUNCTION_DECL:
kono
parents:
diff changeset
1772 case VAR_DECL:
kono
parents:
diff changeset
1773 if (decl_in_symtab_p (t1) && decl_in_symtab_p (t2))
kono
parents:
diff changeset
1774 return true;
kono
parents:
diff changeset
1775 return return_false_with_msg ("Declaration mismatch");
kono
parents:
diff changeset
1776 case CONST_DECL:
kono
parents:
diff changeset
1777 /* TODO: We can check CONST_DECL by its DECL_INITIAL, but for that we
kono
parents:
diff changeset
1778 need to process its VAR/FUNCTION references without relying on ipa-ref
kono
parents:
diff changeset
1779 compare. */
kono
parents:
diff changeset
1780 case FIELD_DECL:
kono
parents:
diff changeset
1781 case LABEL_DECL:
kono
parents:
diff changeset
1782 return return_false_with_msg ("Declaration mismatch");
kono
parents:
diff changeset
1783 case INTEGER_CST:
kono
parents:
diff changeset
1784 /* Integer constants are the same only if the same width of type. */
kono
parents:
diff changeset
1785 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
kono
parents:
diff changeset
1786 return return_false_with_msg ("INTEGER_CST precision mismatch");
kono
parents:
diff changeset
1787 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
kono
parents:
diff changeset
1788 return return_false_with_msg ("INTEGER_CST mode mismatch");
kono
parents:
diff changeset
1789 return return_with_debug (tree_int_cst_equal (t1, t2));
kono
parents:
diff changeset
1790 case STRING_CST:
kono
parents:
diff changeset
1791 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
kono
parents:
diff changeset
1792 return return_false_with_msg ("STRING_CST mode mismatch");
kono
parents:
diff changeset
1793 if (TREE_STRING_LENGTH (t1) != TREE_STRING_LENGTH (t2))
kono
parents:
diff changeset
1794 return return_false_with_msg ("STRING_CST length mismatch");
kono
parents:
diff changeset
1795 if (memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
kono
parents:
diff changeset
1796 TREE_STRING_LENGTH (t1)))
kono
parents:
diff changeset
1797 return return_false_with_msg ("STRING_CST mismatch");
kono
parents:
diff changeset
1798 return true;
kono
parents:
diff changeset
1799 case FIXED_CST:
kono
parents:
diff changeset
1800 /* Fixed constants are the same only if the same width of type. */
kono
parents:
diff changeset
1801 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
kono
parents:
diff changeset
1802 return return_false_with_msg ("FIXED_CST precision mismatch");
kono
parents:
diff changeset
1803
kono
parents:
diff changeset
1804 return return_with_debug (FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
kono
parents:
diff changeset
1805 TREE_FIXED_CST (t2)));
kono
parents:
diff changeset
1806 case COMPLEX_CST:
kono
parents:
diff changeset
1807 return (sem_variable::equals (TREE_REALPART (t1), TREE_REALPART (t2))
kono
parents:
diff changeset
1808 && sem_variable::equals (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
kono
parents:
diff changeset
1809 case REAL_CST:
kono
parents:
diff changeset
1810 /* Real constants are the same only if the same width of type. */
kono
parents:
diff changeset
1811 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
kono
parents:
diff changeset
1812 return return_false_with_msg ("REAL_CST precision mismatch");
kono
parents:
diff changeset
1813 return return_with_debug (real_identical (&TREE_REAL_CST (t1),
kono
parents:
diff changeset
1814 &TREE_REAL_CST (t2)));
kono
parents:
diff changeset
1815 case VECTOR_CST:
kono
parents:
diff changeset
1816 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1817 if (maybe_ne (VECTOR_CST_NELTS (t1), VECTOR_CST_NELTS (t2)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1818 return return_false_with_msg ("VECTOR_CST nelts mismatch");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1819
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1820 unsigned int count
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1821 = tree_vector_builder::binary_encoded_nelts (t1, t2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1822 for (unsigned int i = 0; i < count; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1823 if (!sem_variable::equals (VECTOR_CST_ENCODED_ELT (t1, i),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1824 VECTOR_CST_ENCODED_ELT (t2, i)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1825 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1826
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1827 return true;
111
kono
parents:
diff changeset
1828 }
kono
parents:
diff changeset
1829 case ARRAY_REF:
kono
parents:
diff changeset
1830 case ARRAY_RANGE_REF:
kono
parents:
diff changeset
1831 {
kono
parents:
diff changeset
1832 tree x1 = TREE_OPERAND (t1, 0);
kono
parents:
diff changeset
1833 tree x2 = TREE_OPERAND (t2, 0);
kono
parents:
diff changeset
1834 tree y1 = TREE_OPERAND (t1, 1);
kono
parents:
diff changeset
1835 tree y2 = TREE_OPERAND (t2, 1);
kono
parents:
diff changeset
1836
kono
parents:
diff changeset
1837 if (!sem_variable::equals (x1, x2) || !sem_variable::equals (y1, y2))
kono
parents:
diff changeset
1838 return false;
kono
parents:
diff changeset
1839 if (!sem_variable::equals (array_ref_low_bound (t1),
kono
parents:
diff changeset
1840 array_ref_low_bound (t2)))
kono
parents:
diff changeset
1841 return false;
kono
parents:
diff changeset
1842 if (!sem_variable::equals (array_ref_element_size (t1),
kono
parents:
diff changeset
1843 array_ref_element_size (t2)))
kono
parents:
diff changeset
1844 return false;
kono
parents:
diff changeset
1845 return true;
kono
parents:
diff changeset
1846 }
kono
parents:
diff changeset
1847
kono
parents:
diff changeset
1848 case COMPONENT_REF:
kono
parents:
diff changeset
1849 case POINTER_PLUS_EXPR:
kono
parents:
diff changeset
1850 case PLUS_EXPR:
kono
parents:
diff changeset
1851 case MINUS_EXPR:
kono
parents:
diff changeset
1852 case RANGE_EXPR:
kono
parents:
diff changeset
1853 {
kono
parents:
diff changeset
1854 tree x1 = TREE_OPERAND (t1, 0);
kono
parents:
diff changeset
1855 tree x2 = TREE_OPERAND (t2, 0);
kono
parents:
diff changeset
1856 tree y1 = TREE_OPERAND (t1, 1);
kono
parents:
diff changeset
1857 tree y2 = TREE_OPERAND (t2, 1);
kono
parents:
diff changeset
1858
kono
parents:
diff changeset
1859 return sem_variable::equals (x1, x2) && sem_variable::equals (y1, y2);
kono
parents:
diff changeset
1860 }
kono
parents:
diff changeset
1861
kono
parents:
diff changeset
1862 CASE_CONVERT:
kono
parents:
diff changeset
1863 case VIEW_CONVERT_EXPR:
kono
parents:
diff changeset
1864 if (!func_checker::compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
kono
parents:
diff changeset
1865 return return_false ();
kono
parents:
diff changeset
1866 return sem_variable::equals (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
kono
parents:
diff changeset
1867 case ERROR_MARK:
kono
parents:
diff changeset
1868 return return_false_with_msg ("ERROR_MARK");
kono
parents:
diff changeset
1869 default:
kono
parents:
diff changeset
1870 return return_false_with_msg ("Unknown TREE code reached");
kono
parents:
diff changeset
1871 }
kono
parents:
diff changeset
1872 }
kono
parents:
diff changeset
1873
kono
parents:
diff changeset
1874 /* Parser function that visits a varpool NODE. */
kono
parents:
diff changeset
1875
kono
parents:
diff changeset
1876 sem_variable *
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1877 sem_variable::parse (varpool_node *node, bitmap_obstack *stack,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1878 func_checker *checker)
111
kono
parents:
diff changeset
1879 {
kono
parents:
diff changeset
1880 if (TREE_THIS_VOLATILE (node->decl) || DECL_HARD_REGISTER (node->decl)
kono
parents:
diff changeset
1881 || node->alias)
kono
parents:
diff changeset
1882 return NULL;
kono
parents:
diff changeset
1883
kono
parents:
diff changeset
1884 sem_variable *v = new sem_variable (node, stack);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1885 v->init (checker);
111
kono
parents:
diff changeset
1886
kono
parents:
diff changeset
1887 return v;
kono
parents:
diff changeset
1888 }
kono
parents:
diff changeset
1889
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1890 /* Semantic variable initialization function. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1891
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1892 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1893 sem_variable::init (ipa_icf_gimple::func_checker *checker)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1894 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1895 decl = get_node ()->decl;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1896
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1897 /* All WPA streamed in symbols should have their hashes computed at compile
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1898 time. At this point, the constructor may not be in memory at all.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1899 DECL_INITIAL (decl) would be error_mark_node in that case. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1900 if (!m_hash_set)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1901 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1902 gcc_assert (!node->lto_file_data);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1903 inchash::hash hstate;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1904 hstate.add_int (456346417);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1905 checker->hash_operand (DECL_INITIAL (decl), hstate, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1906 set_hash (hstate.end ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1907 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1908 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1909
111
kono
parents:
diff changeset
1910 /* References independent hash function. */
kono
parents:
diff changeset
1911
kono
parents:
diff changeset
1912 hashval_t
kono
parents:
diff changeset
1913 sem_variable::get_hash (void)
kono
parents:
diff changeset
1914 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1915 gcc_checking_assert (m_hash_set);
111
kono
parents:
diff changeset
1916 return m_hash;
kono
parents:
diff changeset
1917 }
kono
parents:
diff changeset
1918
kono
parents:
diff changeset
1919 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
kono
parents:
diff changeset
1920 be applied. */
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 bool
kono
parents:
diff changeset
1923 sem_variable::merge (sem_item *alias_item)
kono
parents:
diff changeset
1924 {
kono
parents:
diff changeset
1925 gcc_assert (alias_item->type == VAR);
kono
parents:
diff changeset
1926
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1927 AUTO_DUMP_SCOPE ("merge",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1928 dump_user_location_t::from_function_decl (decl));
111
kono
parents:
diff changeset
1929 if (!sem_item::target_supports_symbol_aliases_p ())
kono
parents:
diff changeset
1930 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1931 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1932 dump_printf (MSG_MISSED_OPTIMIZATION, "Not unifying; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1933 "Symbol aliases are not supported by target\n");
111
kono
parents:
diff changeset
1934 return false;
kono
parents:
diff changeset
1935 }
kono
parents:
diff changeset
1936
kono
parents:
diff changeset
1937 if (DECL_EXTERNAL (alias_item->decl))
kono
parents:
diff changeset
1938 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1939 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1940 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1941 "Not unifying; alias is external.\n");
111
kono
parents:
diff changeset
1942 return false;
kono
parents:
diff changeset
1943 }
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 sem_variable *alias_var = static_cast<sem_variable *> (alias_item);
kono
parents:
diff changeset
1946
kono
parents:
diff changeset
1947 varpool_node *original = get_node ();
kono
parents:
diff changeset
1948 varpool_node *alias = alias_var->get_node ();
kono
parents:
diff changeset
1949 bool original_discardable = false;
kono
parents:
diff changeset
1950
kono
parents:
diff changeset
1951 bool alias_address_matters = alias->address_matters_p ();
kono
parents:
diff changeset
1952
kono
parents:
diff changeset
1953 /* See if original is in a section that can be discarded if the main
kono
parents:
diff changeset
1954 symbol is not used.
kono
parents:
diff changeset
1955 Also consider case where we have resolution info and we know that
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1956 original's definition is not going to be used. In this case we cannot
111
kono
parents:
diff changeset
1957 create alias to original. */
kono
parents:
diff changeset
1958 if (original->can_be_discarded_p ()
kono
parents:
diff changeset
1959 || (node->resolution != LDPR_UNKNOWN
kono
parents:
diff changeset
1960 && !decl_binds_to_current_def_p (node->decl)))
kono
parents:
diff changeset
1961 original_discardable = true;
kono
parents:
diff changeset
1962
kono
parents:
diff changeset
1963 gcc_assert (!TREE_ASM_WRITTEN (alias->decl));
kono
parents:
diff changeset
1964
kono
parents:
diff changeset
1965 /* Constant pool machinery is not quite ready for aliases.
kono
parents:
diff changeset
1966 TODO: varasm code contains logic for merging DECL_IN_CONSTANT_POOL.
kono
parents:
diff changeset
1967 For LTO merging does not happen that is an important missing feature.
kono
parents:
diff changeset
1968 We can enable merging with LTO if the DECL_IN_CONSTANT_POOL
kono
parents:
diff changeset
1969 flag is dropped and non-local symbol name is assigned. */
kono
parents:
diff changeset
1970 if (DECL_IN_CONSTANT_POOL (alias->decl)
kono
parents:
diff changeset
1971 || DECL_IN_CONSTANT_POOL (original->decl))
kono
parents:
diff changeset
1972 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1973 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1974 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1975 "Not unifying; constant pool variables.\n");
111
kono
parents:
diff changeset
1976 return false;
kono
parents:
diff changeset
1977 }
kono
parents:
diff changeset
1978
kono
parents:
diff changeset
1979 /* Do not attempt to mix functions from different user sections;
kono
parents:
diff changeset
1980 we do not know what user intends with those. */
kono
parents:
diff changeset
1981 if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
kono
parents:
diff changeset
1982 || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
kono
parents:
diff changeset
1983 && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
kono
parents:
diff changeset
1984 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1985 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1986 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1987 "Not unifying; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1988 "original and alias are in different sections.\n");
111
kono
parents:
diff changeset
1989 return false;
kono
parents:
diff changeset
1990 }
kono
parents:
diff changeset
1991
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1992 /* We cannot merge if address comparison matters. */
111
kono
parents:
diff changeset
1993 if (alias_address_matters && flag_merge_constants < 2)
kono
parents:
diff changeset
1994 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1995 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1996 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1997 "Not unifying; address of original may be compared.\n");
111
kono
parents:
diff changeset
1998 return false;
kono
parents:
diff changeset
1999 }
kono
parents:
diff changeset
2000
kono
parents:
diff changeset
2001 if (DECL_ALIGN (original->decl) < DECL_ALIGN (alias->decl))
kono
parents:
diff changeset
2002 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2003 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2004 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2005 "Not unifying; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2006 "original and alias have incompatible alignments\n");
111
kono
parents:
diff changeset
2007
kono
parents:
diff changeset
2008 return false;
kono
parents:
diff changeset
2009 }
kono
parents:
diff changeset
2010
kono
parents:
diff changeset
2011 if (DECL_COMDAT_GROUP (original->decl) != DECL_COMDAT_GROUP (alias->decl))
kono
parents:
diff changeset
2012 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2013 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2014 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2015 "Not unifying; alias cannot be created; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2016 "across comdat group boundary\n");
111
kono
parents:
diff changeset
2017
kono
parents:
diff changeset
2018 return false;
kono
parents:
diff changeset
2019 }
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 if (original_discardable)
kono
parents:
diff changeset
2022 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2023 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2024 dump_printf (MSG_MISSED_OPTIMIZATION,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2025 "Not unifying; alias cannot be created; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2026 "target is discardable\n");
111
kono
parents:
diff changeset
2027
kono
parents:
diff changeset
2028 return false;
kono
parents:
diff changeset
2029 }
kono
parents:
diff changeset
2030 else
kono
parents:
diff changeset
2031 {
kono
parents:
diff changeset
2032 gcc_assert (!original->alias);
kono
parents:
diff changeset
2033 gcc_assert (!alias->alias);
kono
parents:
diff changeset
2034
kono
parents:
diff changeset
2035 alias->analyzed = false;
kono
parents:
diff changeset
2036
kono
parents:
diff changeset
2037 DECL_INITIAL (alias->decl) = NULL;
kono
parents:
diff changeset
2038 ((symtab_node *)alias)->call_for_symbol_and_aliases (clear_decl_rtl,
kono
parents:
diff changeset
2039 NULL, true);
kono
parents:
diff changeset
2040 alias->remove_all_references ();
kono
parents:
diff changeset
2041 if (TREE_ADDRESSABLE (alias->decl))
kono
parents:
diff changeset
2042 original->call_for_symbol_and_aliases (set_addressable, NULL, true);
kono
parents:
diff changeset
2043
kono
parents:
diff changeset
2044 varpool_node::create_alias (alias_var->decl, decl);
kono
parents:
diff changeset
2045 alias->resolve_alias (original);
kono
parents:
diff changeset
2046
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2047 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2048 dump_printf (MSG_OPTIMIZED_LOCATIONS,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2049 "Unified; Variable alias has been created.\n");
111
kono
parents:
diff changeset
2050
kono
parents:
diff changeset
2051 return true;
kono
parents:
diff changeset
2052 }
kono
parents:
diff changeset
2053 }
kono
parents:
diff changeset
2054
kono
parents:
diff changeset
2055 /* Dump symbol to FILE. */
kono
parents:
diff changeset
2056
kono
parents:
diff changeset
2057 void
kono
parents:
diff changeset
2058 sem_variable::dump_to_file (FILE *file)
kono
parents:
diff changeset
2059 {
kono
parents:
diff changeset
2060 gcc_assert (file);
kono
parents:
diff changeset
2061
kono
parents:
diff changeset
2062 print_node (file, "", decl, 0);
kono
parents:
diff changeset
2063 fprintf (file, "\n\n");
kono
parents:
diff changeset
2064 }
kono
parents:
diff changeset
2065
kono
parents:
diff changeset
2066 unsigned int sem_item_optimizer::class_id = 0;
kono
parents:
diff changeset
2067
kono
parents:
diff changeset
2068 sem_item_optimizer::sem_item_optimizer ()
kono
parents:
diff changeset
2069 : worklist (0), m_classes (0), m_classes_count (0), m_cgraph_node_hooks (NULL),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2070 m_varpool_node_hooks (NULL), m_merged_variables (), m_references ()
111
kono
parents:
diff changeset
2071 {
kono
parents:
diff changeset
2072 m_items.create (0);
kono
parents:
diff changeset
2073 bitmap_obstack_initialize (&m_bmstack);
kono
parents:
diff changeset
2074 }
kono
parents:
diff changeset
2075
kono
parents:
diff changeset
2076 sem_item_optimizer::~sem_item_optimizer ()
kono
parents:
diff changeset
2077 {
kono
parents:
diff changeset
2078 for (unsigned int i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2079 delete m_items[i];
kono
parents:
diff changeset
2080
kono
parents:
diff changeset
2081
kono
parents:
diff changeset
2082 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
2083 it != m_classes.end (); ++it)
kono
parents:
diff changeset
2084 {
kono
parents:
diff changeset
2085 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
2086 delete (*it)->classes[i];
kono
parents:
diff changeset
2087
kono
parents:
diff changeset
2088 (*it)->classes.release ();
kono
parents:
diff changeset
2089 free (*it);
kono
parents:
diff changeset
2090 }
kono
parents:
diff changeset
2091
kono
parents:
diff changeset
2092 m_items.release ();
kono
parents:
diff changeset
2093
kono
parents:
diff changeset
2094 bitmap_obstack_release (&m_bmstack);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2095 m_merged_variables.release ();
111
kono
parents:
diff changeset
2096 }
kono
parents:
diff changeset
2097
kono
parents:
diff changeset
2098 /* Write IPA ICF summary for symbols. */
kono
parents:
diff changeset
2099
kono
parents:
diff changeset
2100 void
kono
parents:
diff changeset
2101 sem_item_optimizer::write_summary (void)
kono
parents:
diff changeset
2102 {
kono
parents:
diff changeset
2103 unsigned int count = 0;
kono
parents:
diff changeset
2104
kono
parents:
diff changeset
2105 output_block *ob = create_output_block (LTO_section_ipa_icf);
kono
parents:
diff changeset
2106 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
kono
parents:
diff changeset
2107 ob->symbol = NULL;
kono
parents:
diff changeset
2108
kono
parents:
diff changeset
2109 /* Calculate number of symbols to be serialized. */
kono
parents:
diff changeset
2110 for (lto_symtab_encoder_iterator lsei = lsei_start_in_partition (encoder);
kono
parents:
diff changeset
2111 !lsei_end_p (lsei);
kono
parents:
diff changeset
2112 lsei_next_in_partition (&lsei))
kono
parents:
diff changeset
2113 {
kono
parents:
diff changeset
2114 symtab_node *node = lsei_node (lsei);
kono
parents:
diff changeset
2115
kono
parents:
diff changeset
2116 if (m_symtab_node_map.get (node))
kono
parents:
diff changeset
2117 count++;
kono
parents:
diff changeset
2118 }
kono
parents:
diff changeset
2119
kono
parents:
diff changeset
2120 streamer_write_uhwi (ob, count);
kono
parents:
diff changeset
2121
kono
parents:
diff changeset
2122 /* Process all of the symbols. */
kono
parents:
diff changeset
2123 for (lto_symtab_encoder_iterator lsei = lsei_start_in_partition (encoder);
kono
parents:
diff changeset
2124 !lsei_end_p (lsei);
kono
parents:
diff changeset
2125 lsei_next_in_partition (&lsei))
kono
parents:
diff changeset
2126 {
kono
parents:
diff changeset
2127 symtab_node *node = lsei_node (lsei);
kono
parents:
diff changeset
2128
kono
parents:
diff changeset
2129 sem_item **item = m_symtab_node_map.get (node);
kono
parents:
diff changeset
2130
kono
parents:
diff changeset
2131 if (item && *item)
kono
parents:
diff changeset
2132 {
kono
parents:
diff changeset
2133 int node_ref = lto_symtab_encoder_encode (encoder, node);
kono
parents:
diff changeset
2134 streamer_write_uhwi_stream (ob->main_stream, node_ref);
kono
parents:
diff changeset
2135
kono
parents:
diff changeset
2136 streamer_write_uhwi (ob, (*item)->get_hash ());
kono
parents:
diff changeset
2137 }
kono
parents:
diff changeset
2138 }
kono
parents:
diff changeset
2139
kono
parents:
diff changeset
2140 streamer_write_char_stream (ob->main_stream, 0);
kono
parents:
diff changeset
2141 produce_asm (ob, NULL);
kono
parents:
diff changeset
2142 destroy_output_block (ob);
kono
parents:
diff changeset
2143 }
kono
parents:
diff changeset
2144
kono
parents:
diff changeset
2145 /* Reads a section from LTO stream file FILE_DATA. Input block for DATA
kono
parents:
diff changeset
2146 contains LEN bytes. */
kono
parents:
diff changeset
2147
kono
parents:
diff changeset
2148 void
kono
parents:
diff changeset
2149 sem_item_optimizer::read_section (lto_file_decl_data *file_data,
kono
parents:
diff changeset
2150 const char *data, size_t len)
kono
parents:
diff changeset
2151 {
kono
parents:
diff changeset
2152 const lto_function_header *header
kono
parents:
diff changeset
2153 = (const lto_function_header *) data;
kono
parents:
diff changeset
2154 const int cfg_offset = sizeof (lto_function_header);
kono
parents:
diff changeset
2155 const int main_offset = cfg_offset + header->cfg_size;
kono
parents:
diff changeset
2156 const int string_offset = main_offset + header->main_size;
kono
parents:
diff changeset
2157 data_in *data_in;
kono
parents:
diff changeset
2158 unsigned int i;
kono
parents:
diff changeset
2159 unsigned int count;
kono
parents:
diff changeset
2160
kono
parents:
diff changeset
2161 lto_input_block ib_main ((const char *) data + main_offset, 0,
kono
parents:
diff changeset
2162 header->main_size, file_data->mode_table);
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 data_in
kono
parents:
diff changeset
2165 = lto_data_in_create (file_data, (const char *) data + string_offset,
kono
parents:
diff changeset
2166 header->string_size, vNULL);
kono
parents:
diff changeset
2167
kono
parents:
diff changeset
2168 count = streamer_read_uhwi (&ib_main);
kono
parents:
diff changeset
2169
kono
parents:
diff changeset
2170 for (i = 0; i < count; i++)
kono
parents:
diff changeset
2171 {
kono
parents:
diff changeset
2172 unsigned int index;
kono
parents:
diff changeset
2173 symtab_node *node;
kono
parents:
diff changeset
2174 lto_symtab_encoder_t encoder;
kono
parents:
diff changeset
2175
kono
parents:
diff changeset
2176 index = streamer_read_uhwi (&ib_main);
kono
parents:
diff changeset
2177 encoder = file_data->symtab_node_encoder;
kono
parents:
diff changeset
2178 node = lto_symtab_encoder_deref (encoder, index);
kono
parents:
diff changeset
2179
kono
parents:
diff changeset
2180 hashval_t hash = streamer_read_uhwi (&ib_main);
kono
parents:
diff changeset
2181 gcc_assert (node->definition);
kono
parents:
diff changeset
2182
kono
parents:
diff changeset
2183 if (is_a<cgraph_node *> (node))
kono
parents:
diff changeset
2184 {
kono
parents:
diff changeset
2185 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
kono
parents:
diff changeset
2186
kono
parents:
diff changeset
2187 sem_function *fn = new sem_function (cnode, &m_bmstack);
kono
parents:
diff changeset
2188 fn->set_hash (hash);
kono
parents:
diff changeset
2189 m_items.safe_push (fn);
kono
parents:
diff changeset
2190 }
kono
parents:
diff changeset
2191 else
kono
parents:
diff changeset
2192 {
kono
parents:
diff changeset
2193 varpool_node *vnode = dyn_cast <varpool_node *> (node);
kono
parents:
diff changeset
2194
kono
parents:
diff changeset
2195 sem_variable *var = new sem_variable (vnode, &m_bmstack);
kono
parents:
diff changeset
2196 var->set_hash (hash);
kono
parents:
diff changeset
2197 m_items.safe_push (var);
kono
parents:
diff changeset
2198 }
kono
parents:
diff changeset
2199 }
kono
parents:
diff changeset
2200
kono
parents:
diff changeset
2201 lto_free_section_data (file_data, LTO_section_ipa_icf, NULL, data,
kono
parents:
diff changeset
2202 len);
kono
parents:
diff changeset
2203 lto_data_in_delete (data_in);
kono
parents:
diff changeset
2204 }
kono
parents:
diff changeset
2205
kono
parents:
diff changeset
2206 /* Read IPA ICF summary for symbols. */
kono
parents:
diff changeset
2207
kono
parents:
diff changeset
2208 void
kono
parents:
diff changeset
2209 sem_item_optimizer::read_summary (void)
kono
parents:
diff changeset
2210 {
kono
parents:
diff changeset
2211 lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
kono
parents:
diff changeset
2212 lto_file_decl_data *file_data;
kono
parents:
diff changeset
2213 unsigned int j = 0;
kono
parents:
diff changeset
2214
kono
parents:
diff changeset
2215 while ((file_data = file_data_vec[j++]))
kono
parents:
diff changeset
2216 {
kono
parents:
diff changeset
2217 size_t len;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2218 const char *data
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2219 = lto_get_summary_section_data (file_data, LTO_section_ipa_icf, &len);
111
kono
parents:
diff changeset
2220 if (data)
kono
parents:
diff changeset
2221 read_section (file_data, data, len);
kono
parents:
diff changeset
2222 }
kono
parents:
diff changeset
2223 }
kono
parents:
diff changeset
2224
kono
parents:
diff changeset
2225 /* Register callgraph and varpool hooks. */
kono
parents:
diff changeset
2226
kono
parents:
diff changeset
2227 void
kono
parents:
diff changeset
2228 sem_item_optimizer::register_hooks (void)
kono
parents:
diff changeset
2229 {
kono
parents:
diff changeset
2230 if (!m_cgraph_node_hooks)
kono
parents:
diff changeset
2231 m_cgraph_node_hooks = symtab->add_cgraph_removal_hook
kono
parents:
diff changeset
2232 (&sem_item_optimizer::cgraph_removal_hook, this);
kono
parents:
diff changeset
2233
kono
parents:
diff changeset
2234 if (!m_varpool_node_hooks)
kono
parents:
diff changeset
2235 m_varpool_node_hooks = symtab->add_varpool_removal_hook
kono
parents:
diff changeset
2236 (&sem_item_optimizer::varpool_removal_hook, this);
kono
parents:
diff changeset
2237 }
kono
parents:
diff changeset
2238
kono
parents:
diff changeset
2239 /* Unregister callgraph and varpool hooks. */
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 void
kono
parents:
diff changeset
2242 sem_item_optimizer::unregister_hooks (void)
kono
parents:
diff changeset
2243 {
kono
parents:
diff changeset
2244 if (m_cgraph_node_hooks)
kono
parents:
diff changeset
2245 symtab->remove_cgraph_removal_hook (m_cgraph_node_hooks);
kono
parents:
diff changeset
2246
kono
parents:
diff changeset
2247 if (m_varpool_node_hooks)
kono
parents:
diff changeset
2248 symtab->remove_varpool_removal_hook (m_varpool_node_hooks);
kono
parents:
diff changeset
2249 }
kono
parents:
diff changeset
2250
kono
parents:
diff changeset
2251 /* Adds a CLS to hashtable associated by hash value. */
kono
parents:
diff changeset
2252
kono
parents:
diff changeset
2253 void
kono
parents:
diff changeset
2254 sem_item_optimizer::add_class (congruence_class *cls)
kono
parents:
diff changeset
2255 {
kono
parents:
diff changeset
2256 gcc_assert (cls->members.length ());
kono
parents:
diff changeset
2257
kono
parents:
diff changeset
2258 congruence_class_group *group
kono
parents:
diff changeset
2259 = get_group_by_hash (cls->members[0]->get_hash (),
kono
parents:
diff changeset
2260 cls->members[0]->type);
kono
parents:
diff changeset
2261 group->classes.safe_push (cls);
kono
parents:
diff changeset
2262 }
kono
parents:
diff changeset
2263
kono
parents:
diff changeset
2264 /* Gets a congruence class group based on given HASH value and TYPE. */
kono
parents:
diff changeset
2265
kono
parents:
diff changeset
2266 congruence_class_group *
kono
parents:
diff changeset
2267 sem_item_optimizer::get_group_by_hash (hashval_t hash, sem_item_type type)
kono
parents:
diff changeset
2268 {
kono
parents:
diff changeset
2269 congruence_class_group *item = XNEW (congruence_class_group);
kono
parents:
diff changeset
2270 item->hash = hash;
kono
parents:
diff changeset
2271 item->type = type;
kono
parents:
diff changeset
2272
kono
parents:
diff changeset
2273 congruence_class_group **slot = m_classes.find_slot (item, INSERT);
kono
parents:
diff changeset
2274
kono
parents:
diff changeset
2275 if (*slot)
kono
parents:
diff changeset
2276 free (item);
kono
parents:
diff changeset
2277 else
kono
parents:
diff changeset
2278 {
kono
parents:
diff changeset
2279 item->classes.create (1);
kono
parents:
diff changeset
2280 *slot = item;
kono
parents:
diff changeset
2281 }
kono
parents:
diff changeset
2282
kono
parents:
diff changeset
2283 return *slot;
kono
parents:
diff changeset
2284 }
kono
parents:
diff changeset
2285
kono
parents:
diff changeset
2286 /* Callgraph removal hook called for a NODE with a custom DATA. */
kono
parents:
diff changeset
2287
kono
parents:
diff changeset
2288 void
kono
parents:
diff changeset
2289 sem_item_optimizer::cgraph_removal_hook (cgraph_node *node, void *data)
kono
parents:
diff changeset
2290 {
kono
parents:
diff changeset
2291 sem_item_optimizer *optimizer = (sem_item_optimizer *) data;
kono
parents:
diff changeset
2292 optimizer->remove_symtab_node (node);
kono
parents:
diff changeset
2293 }
kono
parents:
diff changeset
2294
kono
parents:
diff changeset
2295 /* Varpool removal hook called for a NODE with a custom DATA. */
kono
parents:
diff changeset
2296
kono
parents:
diff changeset
2297 void
kono
parents:
diff changeset
2298 sem_item_optimizer::varpool_removal_hook (varpool_node *node, void *data)
kono
parents:
diff changeset
2299 {
kono
parents:
diff changeset
2300 sem_item_optimizer *optimizer = (sem_item_optimizer *) data;
kono
parents:
diff changeset
2301 optimizer->remove_symtab_node (node);
kono
parents:
diff changeset
2302 }
kono
parents:
diff changeset
2303
kono
parents:
diff changeset
2304 /* Remove symtab NODE triggered by symtab removal hooks. */
kono
parents:
diff changeset
2305
kono
parents:
diff changeset
2306 void
kono
parents:
diff changeset
2307 sem_item_optimizer::remove_symtab_node (symtab_node *node)
kono
parents:
diff changeset
2308 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2309 gcc_assert (m_classes.is_empty ());
111
kono
parents:
diff changeset
2310
kono
parents:
diff changeset
2311 m_removed_items_set.add (node);
kono
parents:
diff changeset
2312 }
kono
parents:
diff changeset
2313
kono
parents:
diff changeset
2314 void
kono
parents:
diff changeset
2315 sem_item_optimizer::remove_item (sem_item *item)
kono
parents:
diff changeset
2316 {
kono
parents:
diff changeset
2317 if (m_symtab_node_map.get (item->node))
kono
parents:
diff changeset
2318 m_symtab_node_map.remove (item->node);
kono
parents:
diff changeset
2319 delete item;
kono
parents:
diff changeset
2320 }
kono
parents:
diff changeset
2321
kono
parents:
diff changeset
2322 /* Removes all callgraph and varpool nodes that are marked by symtab
kono
parents:
diff changeset
2323 as deleted. */
kono
parents:
diff changeset
2324
kono
parents:
diff changeset
2325 void
kono
parents:
diff changeset
2326 sem_item_optimizer::filter_removed_items (void)
kono
parents:
diff changeset
2327 {
kono
parents:
diff changeset
2328 auto_vec <sem_item *> filtered;
kono
parents:
diff changeset
2329
kono
parents:
diff changeset
2330 for (unsigned int i = 0; i < m_items.length(); i++)
kono
parents:
diff changeset
2331 {
kono
parents:
diff changeset
2332 sem_item *item = m_items[i];
kono
parents:
diff changeset
2333
kono
parents:
diff changeset
2334 if (m_removed_items_set.contains (item->node))
kono
parents:
diff changeset
2335 {
kono
parents:
diff changeset
2336 remove_item (item);
kono
parents:
diff changeset
2337 continue;
kono
parents:
diff changeset
2338 }
kono
parents:
diff changeset
2339
kono
parents:
diff changeset
2340 if (item->type == FUNC)
kono
parents:
diff changeset
2341 {
kono
parents:
diff changeset
2342 cgraph_node *cnode = static_cast <sem_function *>(item)->get_node ();
kono
parents:
diff changeset
2343
kono
parents:
diff changeset
2344 if (in_lto_p && (cnode->alias || cnode->body_removed))
kono
parents:
diff changeset
2345 remove_item (item);
kono
parents:
diff changeset
2346 else
kono
parents:
diff changeset
2347 filtered.safe_push (item);
kono
parents:
diff changeset
2348 }
kono
parents:
diff changeset
2349 else /* VAR. */
kono
parents:
diff changeset
2350 {
kono
parents:
diff changeset
2351 if (!flag_ipa_icf_variables)
kono
parents:
diff changeset
2352 remove_item (item);
kono
parents:
diff changeset
2353 else
kono
parents:
diff changeset
2354 {
kono
parents:
diff changeset
2355 /* Filter out non-readonly variables. */
kono
parents:
diff changeset
2356 tree decl = item->decl;
kono
parents:
diff changeset
2357 if (TREE_READONLY (decl))
kono
parents:
diff changeset
2358 filtered.safe_push (item);
kono
parents:
diff changeset
2359 else
kono
parents:
diff changeset
2360 remove_item (item);
kono
parents:
diff changeset
2361 }
kono
parents:
diff changeset
2362 }
kono
parents:
diff changeset
2363 }
kono
parents:
diff changeset
2364
kono
parents:
diff changeset
2365 /* Clean-up of released semantic items. */
kono
parents:
diff changeset
2366
kono
parents:
diff changeset
2367 m_items.release ();
kono
parents:
diff changeset
2368 for (unsigned int i = 0; i < filtered.length(); i++)
kono
parents:
diff changeset
2369 m_items.safe_push (filtered[i]);
kono
parents:
diff changeset
2370 }
kono
parents:
diff changeset
2371
kono
parents:
diff changeset
2372 /* Optimizer entry point which returns true in case it processes
kono
parents:
diff changeset
2373 a merge operation. True is returned if there's a merge operation
kono
parents:
diff changeset
2374 processed. */
kono
parents:
diff changeset
2375
kono
parents:
diff changeset
2376 bool
kono
parents:
diff changeset
2377 sem_item_optimizer::execute (void)
kono
parents:
diff changeset
2378 {
kono
parents:
diff changeset
2379 filter_removed_items ();
kono
parents:
diff changeset
2380 unregister_hooks ();
kono
parents:
diff changeset
2381
kono
parents:
diff changeset
2382 build_graph ();
kono
parents:
diff changeset
2383 update_hash_by_addr_refs ();
kono
parents:
diff changeset
2384 build_hash_based_classes ();
kono
parents:
diff changeset
2385
kono
parents:
diff changeset
2386 if (dump_file)
kono
parents:
diff changeset
2387 fprintf (dump_file, "Dump after hash based groups\n");
kono
parents:
diff changeset
2388 dump_cong_classes ();
kono
parents:
diff changeset
2389
kono
parents:
diff changeset
2390 subdivide_classes_by_equality (true);
kono
parents:
diff changeset
2391
kono
parents:
diff changeset
2392 if (dump_file)
kono
parents:
diff changeset
2393 fprintf (dump_file, "Dump after WPA based types groups\n");
kono
parents:
diff changeset
2394
kono
parents:
diff changeset
2395 dump_cong_classes ();
kono
parents:
diff changeset
2396
kono
parents:
diff changeset
2397 process_cong_reduction ();
kono
parents:
diff changeset
2398 checking_verify_classes ();
kono
parents:
diff changeset
2399
kono
parents:
diff changeset
2400 if (dump_file)
kono
parents:
diff changeset
2401 fprintf (dump_file, "Dump after callgraph-based congruence reduction\n");
kono
parents:
diff changeset
2402
kono
parents:
diff changeset
2403 dump_cong_classes ();
kono
parents:
diff changeset
2404
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2405 unsigned int loaded_symbols = parse_nonsingleton_classes ();
111
kono
parents:
diff changeset
2406 subdivide_classes_by_equality ();
kono
parents:
diff changeset
2407
kono
parents:
diff changeset
2408 if (dump_file)
kono
parents:
diff changeset
2409 fprintf (dump_file, "Dump after full equality comparison of groups\n");
kono
parents:
diff changeset
2410
kono
parents:
diff changeset
2411 dump_cong_classes ();
kono
parents:
diff changeset
2412
kono
parents:
diff changeset
2413 unsigned int prev_class_count = m_classes_count;
kono
parents:
diff changeset
2414
kono
parents:
diff changeset
2415 process_cong_reduction ();
kono
parents:
diff changeset
2416 dump_cong_classes ();
kono
parents:
diff changeset
2417 checking_verify_classes ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2418 bool merged_p = merge_classes (prev_class_count, loaded_symbols);
111
kono
parents:
diff changeset
2419
kono
parents:
diff changeset
2420 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2421 symtab->dump (dump_file);
kono
parents:
diff changeset
2422
kono
parents:
diff changeset
2423 return merged_p;
kono
parents:
diff changeset
2424 }
kono
parents:
diff changeset
2425
kono
parents:
diff changeset
2426 /* Function responsible for visiting all potential functions and
kono
parents:
diff changeset
2427 read-only variables that can be merged. */
kono
parents:
diff changeset
2428
kono
parents:
diff changeset
2429 void
kono
parents:
diff changeset
2430 sem_item_optimizer::parse_funcs_and_vars (void)
kono
parents:
diff changeset
2431 {
kono
parents:
diff changeset
2432 cgraph_node *cnode;
kono
parents:
diff changeset
2433
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2434 /* Create dummy func_checker for hashing purpose. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2435 func_checker checker;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2436
111
kono
parents:
diff changeset
2437 if (flag_ipa_icf_functions)
kono
parents:
diff changeset
2438 FOR_EACH_DEFINED_FUNCTION (cnode)
kono
parents:
diff changeset
2439 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2440 sem_function *f = sem_function::parse (cnode, &m_bmstack, &checker);
111
kono
parents:
diff changeset
2441 if (f)
kono
parents:
diff changeset
2442 {
kono
parents:
diff changeset
2443 m_items.safe_push (f);
kono
parents:
diff changeset
2444 m_symtab_node_map.put (cnode, f);
kono
parents:
diff changeset
2445 }
kono
parents:
diff changeset
2446 }
kono
parents:
diff changeset
2447
kono
parents:
diff changeset
2448 varpool_node *vnode;
kono
parents:
diff changeset
2449
kono
parents:
diff changeset
2450 if (flag_ipa_icf_variables)
kono
parents:
diff changeset
2451 FOR_EACH_DEFINED_VARIABLE (vnode)
kono
parents:
diff changeset
2452 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2453 sem_variable *v = sem_variable::parse (vnode, &m_bmstack, &checker);
111
kono
parents:
diff changeset
2454
kono
parents:
diff changeset
2455 if (v)
kono
parents:
diff changeset
2456 {
kono
parents:
diff changeset
2457 m_items.safe_push (v);
kono
parents:
diff changeset
2458 m_symtab_node_map.put (vnode, v);
kono
parents:
diff changeset
2459 }
kono
parents:
diff changeset
2460 }
kono
parents:
diff changeset
2461 }
kono
parents:
diff changeset
2462
kono
parents:
diff changeset
2463 /* Makes pairing between a congruence class CLS and semantic ITEM. */
kono
parents:
diff changeset
2464
kono
parents:
diff changeset
2465 void
kono
parents:
diff changeset
2466 sem_item_optimizer::add_item_to_class (congruence_class *cls, sem_item *item)
kono
parents:
diff changeset
2467 {
kono
parents:
diff changeset
2468 item->index_in_class = cls->members.length ();
kono
parents:
diff changeset
2469 cls->members.safe_push (item);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2470 cls->referenced_by_count += item->referenced_by_count;
111
kono
parents:
diff changeset
2471 item->cls = cls;
kono
parents:
diff changeset
2472 }
kono
parents:
diff changeset
2473
kono
parents:
diff changeset
2474 /* For each semantic item, append hash values of references. */
kono
parents:
diff changeset
2475
kono
parents:
diff changeset
2476 void
kono
parents:
diff changeset
2477 sem_item_optimizer::update_hash_by_addr_refs ()
kono
parents:
diff changeset
2478 {
kono
parents:
diff changeset
2479 /* First, append to hash sensitive references and class type if it need to
kono
parents:
diff changeset
2480 be matched for ODR. */
kono
parents:
diff changeset
2481 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2482 {
kono
parents:
diff changeset
2483 m_items[i]->update_hash_by_addr_refs (m_symtab_node_map);
kono
parents:
diff changeset
2484 if (m_items[i]->type == FUNC)
kono
parents:
diff changeset
2485 {
kono
parents:
diff changeset
2486 if (TREE_CODE (TREE_TYPE (m_items[i]->decl)) == METHOD_TYPE
kono
parents:
diff changeset
2487 && contains_polymorphic_type_p
kono
parents:
diff changeset
2488 (TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl)))
kono
parents:
diff changeset
2489 && (DECL_CXX_CONSTRUCTOR_P (m_items[i]->decl)
kono
parents:
diff changeset
2490 || (static_cast<sem_function *> (m_items[i])->param_used_p (0)
kono
parents:
diff changeset
2491 && static_cast<sem_function *> (m_items[i])
kono
parents:
diff changeset
2492 ->compare_polymorphic_p ())))
kono
parents:
diff changeset
2493 {
kono
parents:
diff changeset
2494 tree class_type
kono
parents:
diff changeset
2495 = TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl));
kono
parents:
diff changeset
2496 inchash::hash hstate (m_items[i]->get_hash ());
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 if (TYPE_NAME (class_type)
kono
parents:
diff changeset
2499 && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (class_type)))
kono
parents:
diff changeset
2500 hstate.add_hwi
kono
parents:
diff changeset
2501 (IDENTIFIER_HASH_VALUE
kono
parents:
diff changeset
2502 (DECL_ASSEMBLER_NAME (TYPE_NAME (class_type))));
kono
parents:
diff changeset
2503
kono
parents:
diff changeset
2504 m_items[i]->set_hash (hstate.end ());
kono
parents:
diff changeset
2505 }
kono
parents:
diff changeset
2506 }
kono
parents:
diff changeset
2507 }
kono
parents:
diff changeset
2508
kono
parents:
diff changeset
2509 /* Once all symbols have enhanced hash value, we can append
kono
parents:
diff changeset
2510 hash values of symbols that are seen by IPA ICF and are
kono
parents:
diff changeset
2511 references by a semantic item. Newly computed values
kono
parents:
diff changeset
2512 are saved to global_hash member variable. */
kono
parents:
diff changeset
2513 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2514 m_items[i]->update_hash_by_local_refs (m_symtab_node_map);
kono
parents:
diff changeset
2515
kono
parents:
diff changeset
2516 /* Global hash value replace current hash values. */
kono
parents:
diff changeset
2517 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2518 m_items[i]->set_hash (m_items[i]->global_hash);
kono
parents:
diff changeset
2519 }
kono
parents:
diff changeset
2520
kono
parents:
diff changeset
2521 /* Congruence classes are built by hash value. */
kono
parents:
diff changeset
2522
kono
parents:
diff changeset
2523 void
kono
parents:
diff changeset
2524 sem_item_optimizer::build_hash_based_classes (void)
kono
parents:
diff changeset
2525 {
kono
parents:
diff changeset
2526 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2527 {
kono
parents:
diff changeset
2528 sem_item *item = m_items[i];
kono
parents:
diff changeset
2529
kono
parents:
diff changeset
2530 congruence_class_group *group
kono
parents:
diff changeset
2531 = get_group_by_hash (item->get_hash (), item->type);
kono
parents:
diff changeset
2532
kono
parents:
diff changeset
2533 if (!group->classes.length ())
kono
parents:
diff changeset
2534 {
kono
parents:
diff changeset
2535 m_classes_count++;
kono
parents:
diff changeset
2536 group->classes.safe_push (new congruence_class (class_id++));
kono
parents:
diff changeset
2537 }
kono
parents:
diff changeset
2538
kono
parents:
diff changeset
2539 add_item_to_class (group->classes[0], item);
kono
parents:
diff changeset
2540 }
kono
parents:
diff changeset
2541 }
kono
parents:
diff changeset
2542
kono
parents:
diff changeset
2543 /* Build references according to call graph. */
kono
parents:
diff changeset
2544
kono
parents:
diff changeset
2545 void
kono
parents:
diff changeset
2546 sem_item_optimizer::build_graph (void)
kono
parents:
diff changeset
2547 {
kono
parents:
diff changeset
2548 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2549 {
kono
parents:
diff changeset
2550 sem_item *item = m_items[i];
kono
parents:
diff changeset
2551 m_symtab_node_map.put (item->node, item);
kono
parents:
diff changeset
2552
kono
parents:
diff changeset
2553 /* Initialize hash values if we are not in LTO mode. */
kono
parents:
diff changeset
2554 if (!in_lto_p)
kono
parents:
diff changeset
2555 item->get_hash ();
kono
parents:
diff changeset
2556 }
kono
parents:
diff changeset
2557
kono
parents:
diff changeset
2558 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2559 {
kono
parents:
diff changeset
2560 sem_item *item = m_items[i];
kono
parents:
diff changeset
2561
kono
parents:
diff changeset
2562 if (item->type == FUNC)
kono
parents:
diff changeset
2563 {
kono
parents:
diff changeset
2564 cgraph_node *cnode = dyn_cast <cgraph_node *> (item->node);
kono
parents:
diff changeset
2565
kono
parents:
diff changeset
2566 cgraph_edge *e = cnode->callees;
kono
parents:
diff changeset
2567 while (e)
kono
parents:
diff changeset
2568 {
kono
parents:
diff changeset
2569 sem_item **slot = m_symtab_node_map.get
kono
parents:
diff changeset
2570 (e->callee->ultimate_alias_target ());
kono
parents:
diff changeset
2571 if (slot)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2572 item->add_reference (&m_references, *slot);
111
kono
parents:
diff changeset
2573
kono
parents:
diff changeset
2574 e = e->next_callee;
kono
parents:
diff changeset
2575 }
kono
parents:
diff changeset
2576 }
kono
parents:
diff changeset
2577
kono
parents:
diff changeset
2578 ipa_ref *ref = NULL;
kono
parents:
diff changeset
2579 for (unsigned i = 0; item->node->iterate_reference (i, ref); i++)
kono
parents:
diff changeset
2580 {
kono
parents:
diff changeset
2581 sem_item **slot = m_symtab_node_map.get
kono
parents:
diff changeset
2582 (ref->referred->ultimate_alias_target ());
kono
parents:
diff changeset
2583 if (slot)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2584 item->add_reference (&m_references, *slot);
111
kono
parents:
diff changeset
2585 }
kono
parents:
diff changeset
2586 }
kono
parents:
diff changeset
2587 }
kono
parents:
diff changeset
2588
kono
parents:
diff changeset
2589 /* Semantic items in classes having more than one element and initialized.
kono
parents:
diff changeset
2590 In case of WPA, we load function body. */
kono
parents:
diff changeset
2591
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2592 unsigned int
111
kono
parents:
diff changeset
2593 sem_item_optimizer::parse_nonsingleton_classes (void)
kono
parents:
diff changeset
2594 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2595 unsigned int counter = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2596
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2597 /* Create dummy func_checker for hashing purpose. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2598 func_checker checker;
111
kono
parents:
diff changeset
2599
kono
parents:
diff changeset
2600 for (unsigned i = 0; i < m_items.length (); i++)
kono
parents:
diff changeset
2601 if (m_items[i]->cls->members.length () > 1)
kono
parents:
diff changeset
2602 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2603 m_items[i]->init (&checker);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2604 ++counter;
111
kono
parents:
diff changeset
2605 }
kono
parents:
diff changeset
2606
kono
parents:
diff changeset
2607 if (dump_file)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2608 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2609 float f = m_items.length () ? 100.0f * counter / m_items.length () : 0.0f;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2610 fprintf (dump_file, "Init called for %u items (%.2f%%).\n", counter, f);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2611 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2612
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2613 return counter;
111
kono
parents:
diff changeset
2614 }
kono
parents:
diff changeset
2615
kono
parents:
diff changeset
2616 /* Equality function for semantic items is used to subdivide existing
kono
parents:
diff changeset
2617 classes. If IN_WPA, fast equality function is invoked. */
kono
parents:
diff changeset
2618
kono
parents:
diff changeset
2619 void
kono
parents:
diff changeset
2620 sem_item_optimizer::subdivide_classes_by_equality (bool in_wpa)
kono
parents:
diff changeset
2621 {
kono
parents:
diff changeset
2622 for (hash_table <congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
2623 it != m_classes.end (); ++it)
kono
parents:
diff changeset
2624 {
kono
parents:
diff changeset
2625 unsigned int class_count = (*it)->classes.length ();
kono
parents:
diff changeset
2626
kono
parents:
diff changeset
2627 for (unsigned i = 0; i < class_count; i++)
kono
parents:
diff changeset
2628 {
kono
parents:
diff changeset
2629 congruence_class *c = (*it)->classes[i];
kono
parents:
diff changeset
2630
kono
parents:
diff changeset
2631 if (c->members.length() > 1)
kono
parents:
diff changeset
2632 {
kono
parents:
diff changeset
2633 auto_vec <sem_item *> new_vector;
kono
parents:
diff changeset
2634
kono
parents:
diff changeset
2635 sem_item *first = c->members[0];
kono
parents:
diff changeset
2636 new_vector.safe_push (first);
kono
parents:
diff changeset
2637
kono
parents:
diff changeset
2638 unsigned class_split_first = (*it)->classes.length ();
kono
parents:
diff changeset
2639
kono
parents:
diff changeset
2640 for (unsigned j = 1; j < c->members.length (); j++)
kono
parents:
diff changeset
2641 {
kono
parents:
diff changeset
2642 sem_item *item = c->members[j];
kono
parents:
diff changeset
2643
kono
parents:
diff changeset
2644 bool equals
kono
parents:
diff changeset
2645 = in_wpa ? first->equals_wpa (item, m_symtab_node_map)
kono
parents:
diff changeset
2646 : first->equals (item, m_symtab_node_map);
kono
parents:
diff changeset
2647
kono
parents:
diff changeset
2648 if (equals)
kono
parents:
diff changeset
2649 new_vector.safe_push (item);
kono
parents:
diff changeset
2650 else
kono
parents:
diff changeset
2651 {
kono
parents:
diff changeset
2652 bool integrated = false;
kono
parents:
diff changeset
2653
kono
parents:
diff changeset
2654 for (unsigned k = class_split_first;
kono
parents:
diff changeset
2655 k < (*it)->classes.length (); k++)
kono
parents:
diff changeset
2656 {
kono
parents:
diff changeset
2657 sem_item *x = (*it)->classes[k]->members[0];
kono
parents:
diff changeset
2658 bool equals
kono
parents:
diff changeset
2659 = in_wpa ? x->equals_wpa (item, m_symtab_node_map)
kono
parents:
diff changeset
2660 : x->equals (item, m_symtab_node_map);
kono
parents:
diff changeset
2661
kono
parents:
diff changeset
2662 if (equals)
kono
parents:
diff changeset
2663 {
kono
parents:
diff changeset
2664 integrated = true;
kono
parents:
diff changeset
2665 add_item_to_class ((*it)->classes[k], item);
kono
parents:
diff changeset
2666
kono
parents:
diff changeset
2667 break;
kono
parents:
diff changeset
2668 }
kono
parents:
diff changeset
2669 }
kono
parents:
diff changeset
2670
kono
parents:
diff changeset
2671 if (!integrated)
kono
parents:
diff changeset
2672 {
kono
parents:
diff changeset
2673 congruence_class *c
kono
parents:
diff changeset
2674 = new congruence_class (class_id++);
kono
parents:
diff changeset
2675 m_classes_count++;
kono
parents:
diff changeset
2676 add_item_to_class (c, item);
kono
parents:
diff changeset
2677
kono
parents:
diff changeset
2678 (*it)->classes.safe_push (c);
kono
parents:
diff changeset
2679 }
kono
parents:
diff changeset
2680 }
kono
parents:
diff changeset
2681 }
kono
parents:
diff changeset
2682
kono
parents:
diff changeset
2683 // We replace newly created new_vector for the class we've just
kono
parents:
diff changeset
2684 // splitted.
kono
parents:
diff changeset
2685 c->members.release ();
kono
parents:
diff changeset
2686 c->members.create (new_vector.length ());
kono
parents:
diff changeset
2687
kono
parents:
diff changeset
2688 for (unsigned int j = 0; j < new_vector.length (); j++)
kono
parents:
diff changeset
2689 add_item_to_class (c, new_vector[j]);
kono
parents:
diff changeset
2690 }
kono
parents:
diff changeset
2691 }
kono
parents:
diff changeset
2692 }
kono
parents:
diff changeset
2693
kono
parents:
diff changeset
2694 checking_verify_classes ();
kono
parents:
diff changeset
2695 }
kono
parents:
diff changeset
2696
kono
parents:
diff changeset
2697 /* Subdivide classes by address references that members of the class
kono
parents:
diff changeset
2698 reference. Example can be a pair of functions that have an address
kono
parents:
diff changeset
2699 taken from a function. If these addresses are different the class
kono
parents:
diff changeset
2700 is split. */
kono
parents:
diff changeset
2701
kono
parents:
diff changeset
2702 unsigned
kono
parents:
diff changeset
2703 sem_item_optimizer::subdivide_classes_by_sensitive_refs ()
kono
parents:
diff changeset
2704 {
kono
parents:
diff changeset
2705 typedef hash_map <symbol_compare_hash, vec <sem_item *> > subdivide_hash_map;
kono
parents:
diff changeset
2706
kono
parents:
diff changeset
2707 unsigned newly_created_classes = 0;
kono
parents:
diff changeset
2708
kono
parents:
diff changeset
2709 for (hash_table <congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
2710 it != m_classes.end (); ++it)
kono
parents:
diff changeset
2711 {
kono
parents:
diff changeset
2712 unsigned int class_count = (*it)->classes.length ();
kono
parents:
diff changeset
2713 auto_vec<congruence_class *> new_classes;
kono
parents:
diff changeset
2714
kono
parents:
diff changeset
2715 for (unsigned i = 0; i < class_count; i++)
kono
parents:
diff changeset
2716 {
kono
parents:
diff changeset
2717 congruence_class *c = (*it)->classes[i];
kono
parents:
diff changeset
2718
kono
parents:
diff changeset
2719 if (c->members.length() > 1)
kono
parents:
diff changeset
2720 {
kono
parents:
diff changeset
2721 subdivide_hash_map split_map;
kono
parents:
diff changeset
2722
kono
parents:
diff changeset
2723 for (unsigned j = 0; j < c->members.length (); j++)
kono
parents:
diff changeset
2724 {
kono
parents:
diff changeset
2725 sem_item *source_node = c->members[j];
kono
parents:
diff changeset
2726
kono
parents:
diff changeset
2727 symbol_compare_collection *collection
kono
parents:
diff changeset
2728 = new symbol_compare_collection (source_node->node);
kono
parents:
diff changeset
2729
kono
parents:
diff changeset
2730 bool existed;
kono
parents:
diff changeset
2731 vec <sem_item *> *slot
kono
parents:
diff changeset
2732 = &split_map.get_or_insert (collection, &existed);
kono
parents:
diff changeset
2733 gcc_checking_assert (slot);
kono
parents:
diff changeset
2734
kono
parents:
diff changeset
2735 slot->safe_push (source_node);
kono
parents:
diff changeset
2736
kono
parents:
diff changeset
2737 if (existed)
kono
parents:
diff changeset
2738 delete collection;
kono
parents:
diff changeset
2739 }
kono
parents:
diff changeset
2740
kono
parents:
diff changeset
2741 /* If the map contains more than one key, we have to split
kono
parents:
diff changeset
2742 the map appropriately. */
kono
parents:
diff changeset
2743 if (split_map.elements () != 1)
kono
parents:
diff changeset
2744 {
kono
parents:
diff changeset
2745 bool first_class = true;
kono
parents:
diff changeset
2746
kono
parents:
diff changeset
2747 for (subdivide_hash_map::iterator it2 = split_map.begin ();
kono
parents:
diff changeset
2748 it2 != split_map.end (); ++it2)
kono
parents:
diff changeset
2749 {
kono
parents:
diff changeset
2750 congruence_class *new_cls;
kono
parents:
diff changeset
2751 new_cls = new congruence_class (class_id++);
kono
parents:
diff changeset
2752
kono
parents:
diff changeset
2753 for (unsigned k = 0; k < (*it2).second.length (); k++)
kono
parents:
diff changeset
2754 add_item_to_class (new_cls, (*it2).second[k]);
kono
parents:
diff changeset
2755
kono
parents:
diff changeset
2756 worklist_push (new_cls);
kono
parents:
diff changeset
2757 newly_created_classes++;
kono
parents:
diff changeset
2758
kono
parents:
diff changeset
2759 if (first_class)
kono
parents:
diff changeset
2760 {
kono
parents:
diff changeset
2761 (*it)->classes[i] = new_cls;
kono
parents:
diff changeset
2762 first_class = false;
kono
parents:
diff changeset
2763 }
kono
parents:
diff changeset
2764 else
kono
parents:
diff changeset
2765 {
kono
parents:
diff changeset
2766 new_classes.safe_push (new_cls);
kono
parents:
diff changeset
2767 m_classes_count++;
kono
parents:
diff changeset
2768 }
kono
parents:
diff changeset
2769 }
kono
parents:
diff changeset
2770 }
kono
parents:
diff changeset
2771
kono
parents:
diff changeset
2772 /* Release memory. */
kono
parents:
diff changeset
2773 for (subdivide_hash_map::iterator it2 = split_map.begin ();
kono
parents:
diff changeset
2774 it2 != split_map.end (); ++it2)
kono
parents:
diff changeset
2775 {
kono
parents:
diff changeset
2776 delete (*it2).first;
kono
parents:
diff changeset
2777 (*it2).second.release ();
kono
parents:
diff changeset
2778 }
kono
parents:
diff changeset
2779 }
kono
parents:
diff changeset
2780 }
kono
parents:
diff changeset
2781
kono
parents:
diff changeset
2782 for (unsigned i = 0; i < new_classes.length (); i++)
kono
parents:
diff changeset
2783 (*it)->classes.safe_push (new_classes[i]);
kono
parents:
diff changeset
2784 }
kono
parents:
diff changeset
2785
kono
parents:
diff changeset
2786 return newly_created_classes;
kono
parents:
diff changeset
2787 }
kono
parents:
diff changeset
2788
kono
parents:
diff changeset
2789 /* Verify congruence classes, if checking is enabled. */
kono
parents:
diff changeset
2790
kono
parents:
diff changeset
2791 void
kono
parents:
diff changeset
2792 sem_item_optimizer::checking_verify_classes (void)
kono
parents:
diff changeset
2793 {
kono
parents:
diff changeset
2794 if (flag_checking)
kono
parents:
diff changeset
2795 verify_classes ();
kono
parents:
diff changeset
2796 }
kono
parents:
diff changeset
2797
kono
parents:
diff changeset
2798 /* Verify congruence classes. */
kono
parents:
diff changeset
2799
kono
parents:
diff changeset
2800 void
kono
parents:
diff changeset
2801 sem_item_optimizer::verify_classes (void)
kono
parents:
diff changeset
2802 {
kono
parents:
diff changeset
2803 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
2804 it != m_classes.end (); ++it)
kono
parents:
diff changeset
2805 {
kono
parents:
diff changeset
2806 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
2807 {
kono
parents:
diff changeset
2808 congruence_class *cls = (*it)->classes[i];
kono
parents:
diff changeset
2809
kono
parents:
diff changeset
2810 gcc_assert (cls);
kono
parents:
diff changeset
2811 gcc_assert (cls->members.length () > 0);
kono
parents:
diff changeset
2812
kono
parents:
diff changeset
2813 for (unsigned int j = 0; j < cls->members.length (); j++)
kono
parents:
diff changeset
2814 {
kono
parents:
diff changeset
2815 sem_item *item = cls->members[j];
kono
parents:
diff changeset
2816
kono
parents:
diff changeset
2817 gcc_assert (item);
kono
parents:
diff changeset
2818 gcc_assert (item->cls == cls);
kono
parents:
diff changeset
2819 }
kono
parents:
diff changeset
2820 }
kono
parents:
diff changeset
2821 }
kono
parents:
diff changeset
2822 }
kono
parents:
diff changeset
2823
kono
parents:
diff changeset
2824 /* Disposes split map traverse function. CLS_PTR is pointer to congruence
kono
parents:
diff changeset
2825 class, BSLOT is bitmap slot we want to release. DATA is mandatory,
kono
parents:
diff changeset
2826 but unused argument. */
kono
parents:
diff changeset
2827
kono
parents:
diff changeset
2828 bool
kono
parents:
diff changeset
2829 sem_item_optimizer::release_split_map (congruence_class * const &,
kono
parents:
diff changeset
2830 bitmap const &b, traverse_split_pair *)
kono
parents:
diff changeset
2831 {
kono
parents:
diff changeset
2832 bitmap bmp = b;
kono
parents:
diff changeset
2833
kono
parents:
diff changeset
2834 BITMAP_FREE (bmp);
kono
parents:
diff changeset
2835
kono
parents:
diff changeset
2836 return true;
kono
parents:
diff changeset
2837 }
kono
parents:
diff changeset
2838
kono
parents:
diff changeset
2839 /* Process split operation for a class given as pointer CLS_PTR,
kono
parents:
diff changeset
2840 where bitmap B splits congruence class members. DATA is used
kono
parents:
diff changeset
2841 as argument of split pair. */
kono
parents:
diff changeset
2842
kono
parents:
diff changeset
2843 bool
kono
parents:
diff changeset
2844 sem_item_optimizer::traverse_congruence_split (congruence_class * const &cls,
kono
parents:
diff changeset
2845 bitmap const &b,
kono
parents:
diff changeset
2846 traverse_split_pair *pair)
kono
parents:
diff changeset
2847 {
kono
parents:
diff changeset
2848 sem_item_optimizer *optimizer = pair->optimizer;
kono
parents:
diff changeset
2849 const congruence_class *splitter_cls = pair->cls;
kono
parents:
diff changeset
2850
kono
parents:
diff changeset
2851 /* If counted bits are greater than zero and less than the number of members
kono
parents:
diff changeset
2852 a group will be splitted. */
kono
parents:
diff changeset
2853 unsigned popcount = bitmap_count_bits (b);
kono
parents:
diff changeset
2854
kono
parents:
diff changeset
2855 if (popcount > 0 && popcount < cls->members.length ())
kono
parents:
diff changeset
2856 {
kono
parents:
diff changeset
2857 auto_vec <congruence_class *, 2> newclasses;
kono
parents:
diff changeset
2858 newclasses.quick_push (new congruence_class (class_id++));
kono
parents:
diff changeset
2859 newclasses.quick_push (new congruence_class (class_id++));
kono
parents:
diff changeset
2860
kono
parents:
diff changeset
2861 for (unsigned int i = 0; i < cls->members.length (); i++)
kono
parents:
diff changeset
2862 {
kono
parents:
diff changeset
2863 int target = bitmap_bit_p (b, i);
kono
parents:
diff changeset
2864 congruence_class *tc = newclasses[target];
kono
parents:
diff changeset
2865
kono
parents:
diff changeset
2866 add_item_to_class (tc, cls->members[i]);
kono
parents:
diff changeset
2867 }
kono
parents:
diff changeset
2868
kono
parents:
diff changeset
2869 if (flag_checking)
kono
parents:
diff changeset
2870 {
kono
parents:
diff changeset
2871 for (unsigned int i = 0; i < 2; i++)
kono
parents:
diff changeset
2872 gcc_assert (newclasses[i]->members.length ());
kono
parents:
diff changeset
2873 }
kono
parents:
diff changeset
2874
kono
parents:
diff changeset
2875 if (splitter_cls == cls)
kono
parents:
diff changeset
2876 optimizer->splitter_class_removed = true;
kono
parents:
diff changeset
2877
kono
parents:
diff changeset
2878 /* Remove old class from worklist if presented. */
kono
parents:
diff changeset
2879 bool in_worklist = cls->in_worklist;
kono
parents:
diff changeset
2880
kono
parents:
diff changeset
2881 if (in_worklist)
kono
parents:
diff changeset
2882 cls->in_worklist = false;
kono
parents:
diff changeset
2883
kono
parents:
diff changeset
2884 congruence_class_group g;
kono
parents:
diff changeset
2885 g.hash = cls->members[0]->get_hash ();
kono
parents:
diff changeset
2886 g.type = cls->members[0]->type;
kono
parents:
diff changeset
2887
kono
parents:
diff changeset
2888 congruence_class_group *slot = optimizer->m_classes.find (&g);
kono
parents:
diff changeset
2889
kono
parents:
diff changeset
2890 for (unsigned int i = 0; i < slot->classes.length (); i++)
kono
parents:
diff changeset
2891 if (slot->classes[i] == cls)
kono
parents:
diff changeset
2892 {
kono
parents:
diff changeset
2893 slot->classes.ordered_remove (i);
kono
parents:
diff changeset
2894 break;
kono
parents:
diff changeset
2895 }
kono
parents:
diff changeset
2896
kono
parents:
diff changeset
2897 /* New class will be inserted and integrated to work list. */
kono
parents:
diff changeset
2898 for (unsigned int i = 0; i < 2; i++)
kono
parents:
diff changeset
2899 optimizer->add_class (newclasses[i]);
kono
parents:
diff changeset
2900
kono
parents:
diff changeset
2901 /* Two classes replace one, so that increment just by one. */
kono
parents:
diff changeset
2902 optimizer->m_classes_count++;
kono
parents:
diff changeset
2903
kono
parents:
diff changeset
2904 /* If OLD class was presented in the worklist, we remove the class
kono
parents:
diff changeset
2905 and replace it will both newly created classes. */
kono
parents:
diff changeset
2906 if (in_worklist)
kono
parents:
diff changeset
2907 for (unsigned int i = 0; i < 2; i++)
kono
parents:
diff changeset
2908 optimizer->worklist_push (newclasses[i]);
kono
parents:
diff changeset
2909 else /* Just smaller class is inserted. */
kono
parents:
diff changeset
2910 {
kono
parents:
diff changeset
2911 unsigned int smaller_index
kono
parents:
diff changeset
2912 = (newclasses[0]->members.length ()
kono
parents:
diff changeset
2913 < newclasses[1]->members.length ()
kono
parents:
diff changeset
2914 ? 0 : 1);
kono
parents:
diff changeset
2915 optimizer->worklist_push (newclasses[smaller_index]);
kono
parents:
diff changeset
2916 }
kono
parents:
diff changeset
2917
kono
parents:
diff changeset
2918 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2919 {
kono
parents:
diff changeset
2920 fprintf (dump_file, " congruence class splitted:\n");
kono
parents:
diff changeset
2921 cls->dump (dump_file, 4);
kono
parents:
diff changeset
2922
kono
parents:
diff changeset
2923 fprintf (dump_file, " newly created groups:\n");
kono
parents:
diff changeset
2924 for (unsigned int i = 0; i < 2; i++)
kono
parents:
diff changeset
2925 newclasses[i]->dump (dump_file, 4);
kono
parents:
diff changeset
2926 }
kono
parents:
diff changeset
2927
kono
parents:
diff changeset
2928 /* Release class if not presented in work list. */
kono
parents:
diff changeset
2929 if (!in_worklist)
kono
parents:
diff changeset
2930 delete cls;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2931
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2932 return true;
111
kono
parents:
diff changeset
2933 }
kono
parents:
diff changeset
2934
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2935 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2936 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2937
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2938 /* Compare function for sorting pairs in do_congruence_step_f. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2939
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2940 int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2941 sem_item_optimizer::sort_congruence_split (const void *a_, const void *b_)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2942 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2943 const std::pair<congruence_class *, bitmap> *a
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2944 = (const std::pair<congruence_class *, bitmap> *)a_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2945 const std::pair<congruence_class *, bitmap> *b
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2946 = (const std::pair<congruence_class *, bitmap> *)b_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2947 if (a->first->id < b->first->id)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2948 return -1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2949 else if (a->first->id > b->first->id)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2950 return 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2951 return 0;
111
kono
parents:
diff changeset
2952 }
kono
parents:
diff changeset
2953
kono
parents:
diff changeset
2954 /* Tests if a class CLS used as INDEXth splits any congruence classes.
kono
parents:
diff changeset
2955 Bitmap stack BMSTACK is used for bitmap allocation. */
kono
parents:
diff changeset
2956
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2957 bool
111
kono
parents:
diff changeset
2958 sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
kono
parents:
diff changeset
2959 unsigned int index)
kono
parents:
diff changeset
2960 {
kono
parents:
diff changeset
2961 hash_map <congruence_class *, bitmap> split_map;
kono
parents:
diff changeset
2962
kono
parents:
diff changeset
2963 for (unsigned int i = 0; i < cls->members.length (); i++)
kono
parents:
diff changeset
2964 {
kono
parents:
diff changeset
2965 sem_item *item = cls->members[i];
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2966 sem_usage_pair needle (item, index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2967 vec<sem_item *> *callers = m_references.get (&needle);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2968 if (callers == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2969 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2970
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2971 for (unsigned int j = 0; j < callers->length (); j++)
111
kono
parents:
diff changeset
2972 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2973 sem_item *caller = (*callers)[j];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2974 if (caller->cls->members.length () < 2)
111
kono
parents:
diff changeset
2975 continue;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2976 bitmap *slot = split_map.get (caller->cls);
111
kono
parents:
diff changeset
2977 bitmap b;
kono
parents:
diff changeset
2978
kono
parents:
diff changeset
2979 if(!slot)
kono
parents:
diff changeset
2980 {
kono
parents:
diff changeset
2981 b = BITMAP_ALLOC (&m_bmstack);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2982 split_map.put (caller->cls, b);
111
kono
parents:
diff changeset
2983 }
kono
parents:
diff changeset
2984 else
kono
parents:
diff changeset
2985 b = *slot;
kono
parents:
diff changeset
2986
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2987 gcc_checking_assert (caller->cls);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2988 gcc_checking_assert (caller->index_in_class
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2989 < caller->cls->members.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2990
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2991 bitmap_set_bit (b, caller->index_in_class);
111
kono
parents:
diff changeset
2992 }
kono
parents:
diff changeset
2993 }
kono
parents:
diff changeset
2994
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2995 auto_vec<std::pair<congruence_class *, bitmap> > to_split;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2996 to_split.reserve_exact (split_map.elements ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2997 for (hash_map <congruence_class *, bitmap>::iterator i = split_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2998 i != split_map.end (); ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2999 to_split.safe_push (*i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3000 to_split.qsort (sort_congruence_split);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3001
111
kono
parents:
diff changeset
3002 traverse_split_pair pair;
kono
parents:
diff changeset
3003 pair.optimizer = this;
kono
parents:
diff changeset
3004 pair.cls = cls;
kono
parents:
diff changeset
3005
kono
parents:
diff changeset
3006 splitter_class_removed = false;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3007 bool r = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3008 for (unsigned i = 0; i < to_split.length (); ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3009 r |= traverse_congruence_split (to_split[i].first, to_split[i].second,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3010 &pair);
111
kono
parents:
diff changeset
3011
kono
parents:
diff changeset
3012 /* Bitmap clean-up. */
kono
parents:
diff changeset
3013 split_map.traverse <traverse_split_pair *,
kono
parents:
diff changeset
3014 sem_item_optimizer::release_split_map> (NULL);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3015
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3016 return r;
111
kono
parents:
diff changeset
3017 }
kono
parents:
diff changeset
3018
kono
parents:
diff changeset
3019 /* Every usage of a congruence class CLS is a candidate that can split the
kono
parents:
diff changeset
3020 collection of classes. Bitmap stack BMSTACK is used for bitmap
kono
parents:
diff changeset
3021 allocation. */
kono
parents:
diff changeset
3022
kono
parents:
diff changeset
3023 void
kono
parents:
diff changeset
3024 sem_item_optimizer::do_congruence_step (congruence_class *cls)
kono
parents:
diff changeset
3025 {
kono
parents:
diff changeset
3026 bitmap_iterator bi;
kono
parents:
diff changeset
3027 unsigned int i;
kono
parents:
diff changeset
3028
kono
parents:
diff changeset
3029 bitmap usage = BITMAP_ALLOC (&m_bmstack);
kono
parents:
diff changeset
3030
kono
parents:
diff changeset
3031 for (unsigned int i = 0; i < cls->members.length (); i++)
kono
parents:
diff changeset
3032 bitmap_ior_into (usage, cls->members[i]->usage_index_bitmap);
kono
parents:
diff changeset
3033
kono
parents:
diff changeset
3034 EXECUTE_IF_SET_IN_BITMAP (usage, 0, i, bi)
kono
parents:
diff changeset
3035 {
kono
parents:
diff changeset
3036 if (dump_file && (dump_flags & TDF_DETAILS))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3037 fprintf (dump_file, " processing congruence step for class: %u "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3038 "(%u items, %u references), index: %u\n", cls->id,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3039 cls->referenced_by_count, cls->members.length (), i);
111
kono
parents:
diff changeset
3040 do_congruence_step_for_index (cls, i);
kono
parents:
diff changeset
3041
kono
parents:
diff changeset
3042 if (splitter_class_removed)
kono
parents:
diff changeset
3043 break;
kono
parents:
diff changeset
3044 }
kono
parents:
diff changeset
3045
kono
parents:
diff changeset
3046 BITMAP_FREE (usage);
kono
parents:
diff changeset
3047 }
kono
parents:
diff changeset
3048
kono
parents:
diff changeset
3049 /* Adds a newly created congruence class CLS to worklist. */
kono
parents:
diff changeset
3050
kono
parents:
diff changeset
3051 void
kono
parents:
diff changeset
3052 sem_item_optimizer::worklist_push (congruence_class *cls)
kono
parents:
diff changeset
3053 {
kono
parents:
diff changeset
3054 /* Return if the class CLS is already presented in work list. */
kono
parents:
diff changeset
3055 if (cls->in_worklist)
kono
parents:
diff changeset
3056 return;
kono
parents:
diff changeset
3057
kono
parents:
diff changeset
3058 cls->in_worklist = true;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3059 worklist.insert (cls->referenced_by_count, cls);
111
kono
parents:
diff changeset
3060 }
kono
parents:
diff changeset
3061
kono
parents:
diff changeset
3062 /* Pops a class from worklist. */
kono
parents:
diff changeset
3063
kono
parents:
diff changeset
3064 congruence_class *
kono
parents:
diff changeset
3065 sem_item_optimizer::worklist_pop (void)
kono
parents:
diff changeset
3066 {
kono
parents:
diff changeset
3067 congruence_class *cls;
kono
parents:
diff changeset
3068
kono
parents:
diff changeset
3069 while (!worklist.empty ())
kono
parents:
diff changeset
3070 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3071 cls = worklist.extract_min ();
111
kono
parents:
diff changeset
3072 if (cls->in_worklist)
kono
parents:
diff changeset
3073 {
kono
parents:
diff changeset
3074 cls->in_worklist = false;
kono
parents:
diff changeset
3075
kono
parents:
diff changeset
3076 return cls;
kono
parents:
diff changeset
3077 }
kono
parents:
diff changeset
3078 else
kono
parents:
diff changeset
3079 {
kono
parents:
diff changeset
3080 /* Work list item was already intended to be removed.
kono
parents:
diff changeset
3081 The only reason for doing it is to split a class.
kono
parents:
diff changeset
3082 Thus, the class CLS is deleted. */
kono
parents:
diff changeset
3083 delete cls;
kono
parents:
diff changeset
3084 }
kono
parents:
diff changeset
3085 }
kono
parents:
diff changeset
3086
kono
parents:
diff changeset
3087 return NULL;
kono
parents:
diff changeset
3088 }
kono
parents:
diff changeset
3089
kono
parents:
diff changeset
3090 /* Iterative congruence reduction function. */
kono
parents:
diff changeset
3091
kono
parents:
diff changeset
3092 void
kono
parents:
diff changeset
3093 sem_item_optimizer::process_cong_reduction (void)
kono
parents:
diff changeset
3094 {
kono
parents:
diff changeset
3095 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
3096 it != m_classes.end (); ++it)
kono
parents:
diff changeset
3097 for (unsigned i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
3098 if ((*it)->classes[i]->is_class_used ())
kono
parents:
diff changeset
3099 worklist_push ((*it)->classes[i]);
kono
parents:
diff changeset
3100
kono
parents:
diff changeset
3101 if (dump_file)
kono
parents:
diff changeset
3102 fprintf (dump_file, "Worklist has been filled with: %lu\n",
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3103 (unsigned long) worklist.nodes ());
111
kono
parents:
diff changeset
3104
kono
parents:
diff changeset
3105 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3106 fprintf (dump_file, "Congruence class reduction\n");
kono
parents:
diff changeset
3107
kono
parents:
diff changeset
3108 congruence_class *cls;
kono
parents:
diff changeset
3109
kono
parents:
diff changeset
3110 /* Process complete congruence reduction. */
kono
parents:
diff changeset
3111 while ((cls = worklist_pop ()) != NULL)
kono
parents:
diff changeset
3112 do_congruence_step (cls);
kono
parents:
diff changeset
3113
kono
parents:
diff changeset
3114 /* Subdivide newly created classes according to references. */
kono
parents:
diff changeset
3115 unsigned new_classes = subdivide_classes_by_sensitive_refs ();
kono
parents:
diff changeset
3116
kono
parents:
diff changeset
3117 if (dump_file)
kono
parents:
diff changeset
3118 fprintf (dump_file, "Address reference subdivision created: %u "
kono
parents:
diff changeset
3119 "new classes.\n", new_classes);
kono
parents:
diff changeset
3120 }
kono
parents:
diff changeset
3121
kono
parents:
diff changeset
3122 /* Debug function prints all informations about congruence classes. */
kono
parents:
diff changeset
3123
kono
parents:
diff changeset
3124 void
kono
parents:
diff changeset
3125 sem_item_optimizer::dump_cong_classes (void)
kono
parents:
diff changeset
3126 {
kono
parents:
diff changeset
3127 if (!dump_file)
kono
parents:
diff changeset
3128 return;
kono
parents:
diff changeset
3129
kono
parents:
diff changeset
3130 /* Histogram calculation. */
kono
parents:
diff changeset
3131 unsigned int max_index = 0;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3132 unsigned int single_element_classes = 0;
111
kono
parents:
diff changeset
3133 unsigned int* histogram = XCNEWVEC (unsigned int, m_items.length () + 1);
kono
parents:
diff changeset
3134
kono
parents:
diff changeset
3135 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
3136 it != m_classes.end (); ++it)
kono
parents:
diff changeset
3137 for (unsigned i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
3138 {
kono
parents:
diff changeset
3139 unsigned int c = (*it)->classes[i]->members.length ();
kono
parents:
diff changeset
3140 histogram[c]++;
kono
parents:
diff changeset
3141
kono
parents:
diff changeset
3142 if (c > max_index)
kono
parents:
diff changeset
3143 max_index = c;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3144
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3145 if (c == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3146 ++single_element_classes;
111
kono
parents:
diff changeset
3147 }
kono
parents:
diff changeset
3148
kono
parents:
diff changeset
3149 fprintf (dump_file,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3150 "Congruence classes: %lu with total: %u items (in a non-singular "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3151 "class: %u)\n", (unsigned long) m_classes.elements (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3152 m_items.length (), m_items.length () - single_element_classes);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3153 fprintf (dump_file,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3154 "Class size histogram [number of members]: number of classes\n");
111
kono
parents:
diff changeset
3155 for (unsigned int i = 0; i <= max_index; i++)
kono
parents:
diff changeset
3156 if (histogram[i])
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3157 fprintf (dump_file, "%6u: %6u\n", i, histogram[i]);
111
kono
parents:
diff changeset
3158
kono
parents:
diff changeset
3159 if (dump_flags & TDF_DETAILS)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3160 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3161 it != m_classes.end (); ++it)
111
kono
parents:
diff changeset
3162 {
kono
parents:
diff changeset
3163 fprintf (dump_file, " group: with %u classes:\n",
kono
parents:
diff changeset
3164 (*it)->classes.length ());
kono
parents:
diff changeset
3165
kono
parents:
diff changeset
3166 for (unsigned i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
3167 {
kono
parents:
diff changeset
3168 (*it)->classes[i]->dump (dump_file, 4);
kono
parents:
diff changeset
3169
kono
parents:
diff changeset
3170 if (i < (*it)->classes.length () - 1)
kono
parents:
diff changeset
3171 fprintf (dump_file, " ");
kono
parents:
diff changeset
3172 }
kono
parents:
diff changeset
3173 }
kono
parents:
diff changeset
3174
kono
parents:
diff changeset
3175 free (histogram);
kono
parents:
diff changeset
3176 }
kono
parents:
diff changeset
3177
kono
parents:
diff changeset
3178 /* Sort pair of sem_items A and B by DECL_UID. */
kono
parents:
diff changeset
3179
kono
parents:
diff changeset
3180 static int
kono
parents:
diff changeset
3181 sort_sem_items_by_decl_uid (const void *a, const void *b)
kono
parents:
diff changeset
3182 {
kono
parents:
diff changeset
3183 const sem_item *i1 = *(const sem_item * const *)a;
kono
parents:
diff changeset
3184 const sem_item *i2 = *(const sem_item * const *)b;
kono
parents:
diff changeset
3185
kono
parents:
diff changeset
3186 int uid1 = DECL_UID (i1->decl);
kono
parents:
diff changeset
3187 int uid2 = DECL_UID (i2->decl);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3188 return uid1 - uid2;
111
kono
parents:
diff changeset
3189 }
kono
parents:
diff changeset
3190
kono
parents:
diff changeset
3191 /* Sort pair of congruence_classes A and B by DECL_UID of the first member. */
kono
parents:
diff changeset
3192
kono
parents:
diff changeset
3193 static int
kono
parents:
diff changeset
3194 sort_congruence_classes_by_decl_uid (const void *a, const void *b)
kono
parents:
diff changeset
3195 {
kono
parents:
diff changeset
3196 const congruence_class *c1 = *(const congruence_class * const *)a;
kono
parents:
diff changeset
3197 const congruence_class *c2 = *(const congruence_class * const *)b;
kono
parents:
diff changeset
3198
kono
parents:
diff changeset
3199 int uid1 = DECL_UID (c1->members[0]->decl);
kono
parents:
diff changeset
3200 int uid2 = DECL_UID (c2->members[0]->decl);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3201 return uid1 - uid2;
111
kono
parents:
diff changeset
3202 }
kono
parents:
diff changeset
3203
kono
parents:
diff changeset
3204 /* Sort pair of congruence_class_groups A and B by
kono
parents:
diff changeset
3205 DECL_UID of the first member of a first group. */
kono
parents:
diff changeset
3206
kono
parents:
diff changeset
3207 static int
kono
parents:
diff changeset
3208 sort_congruence_class_groups_by_decl_uid (const void *a, const void *b)
kono
parents:
diff changeset
3209 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3210 const std::pair<congruence_class_group *, int> *g1
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3211 = (const std::pair<congruence_class_group *, int> *) a;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3212 const std::pair<congruence_class_group *, int> *g2
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3213 = (const std::pair<congruence_class_group *, int> *) b;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3214 return g1->second - g2->second;
111
kono
parents:
diff changeset
3215 }
kono
parents:
diff changeset
3216
kono
parents:
diff changeset
3217 /* After reduction is done, we can declare all items in a group
kono
parents:
diff changeset
3218 to be equal. PREV_CLASS_COUNT is start number of classes
kono
parents:
diff changeset
3219 before reduction. True is returned if there's a merge operation
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3220 processed. LOADED_SYMBOLS is number of symbols that were loaded
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3221 in WPA. */
111
kono
parents:
diff changeset
3222
kono
parents:
diff changeset
3223 bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3224 sem_item_optimizer::merge_classes (unsigned int prev_class_count,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3225 unsigned int loaded_symbols)
111
kono
parents:
diff changeset
3226 {
kono
parents:
diff changeset
3227 unsigned int item_count = m_items.length ();
kono
parents:
diff changeset
3228 unsigned int class_count = m_classes_count;
kono
parents:
diff changeset
3229 unsigned int equal_items = item_count - class_count;
kono
parents:
diff changeset
3230
kono
parents:
diff changeset
3231 unsigned int non_singular_classes_count = 0;
kono
parents:
diff changeset
3232 unsigned int non_singular_classes_sum = 0;
kono
parents:
diff changeset
3233
kono
parents:
diff changeset
3234 bool merged_p = false;
kono
parents:
diff changeset
3235
kono
parents:
diff changeset
3236 /* PR lto/78211
kono
parents:
diff changeset
3237 Sort functions in congruence classes by DECL_UID and do the same
kono
parents:
diff changeset
3238 for the classes to not to break -fcompare-debug. */
kono
parents:
diff changeset
3239
kono
parents:
diff changeset
3240 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
3241 it != m_classes.end (); ++it)
kono
parents:
diff changeset
3242 {
kono
parents:
diff changeset
3243 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
3244 {
kono
parents:
diff changeset
3245 congruence_class *c = (*it)->classes[i];
kono
parents:
diff changeset
3246 c->members.qsort (sort_sem_items_by_decl_uid);
kono
parents:
diff changeset
3247 }
kono
parents:
diff changeset
3248
kono
parents:
diff changeset
3249 (*it)->classes.qsort (sort_congruence_classes_by_decl_uid);
kono
parents:
diff changeset
3250 }
kono
parents:
diff changeset
3251
kono
parents:
diff changeset
3252 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
3253 it != m_classes.end (); ++it)
kono
parents:
diff changeset
3254 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
kono
parents:
diff changeset
3255 {
kono
parents:
diff changeset
3256 congruence_class *c = (*it)->classes[i];
kono
parents:
diff changeset
3257 if (c->members.length () > 1)
kono
parents:
diff changeset
3258 {
kono
parents:
diff changeset
3259 non_singular_classes_count++;
kono
parents:
diff changeset
3260 non_singular_classes_sum += c->members.length ();
kono
parents:
diff changeset
3261 }
kono
parents:
diff changeset
3262 }
kono
parents:
diff changeset
3263
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3264 auto_vec<std::pair<congruence_class_group *, int> > classes (
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3265 m_classes.elements ());
111
kono
parents:
diff changeset
3266 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
kono
parents:
diff changeset
3267 it != m_classes.end (); ++it)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3268 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3269 int uid = DECL_UID ((*it)->classes[0]->members[0]->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3270 classes.quick_push (std::pair<congruence_class_group *, int> (*it, uid));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3271 }
111
kono
parents:
diff changeset
3272
kono
parents:
diff changeset
3273 classes.qsort (sort_congruence_class_groups_by_decl_uid);
kono
parents:
diff changeset
3274
kono
parents:
diff changeset
3275 if (dump_file)
kono
parents:
diff changeset
3276 {
kono
parents:
diff changeset
3277 fprintf (dump_file, "\nItem count: %u\n", item_count);
kono
parents:
diff changeset
3278 fprintf (dump_file, "Congruent classes before: %u, after: %u\n",
kono
parents:
diff changeset
3279 prev_class_count, class_count);
kono
parents:
diff changeset
3280 fprintf (dump_file, "Average class size before: %.2f, after: %.2f\n",
kono
parents:
diff changeset
3281 prev_class_count ? 1.0f * item_count / prev_class_count : 0.0f,
kono
parents:
diff changeset
3282 class_count ? 1.0f * item_count / class_count : 0.0f);
kono
parents:
diff changeset
3283 fprintf (dump_file, "Average non-singular class size: %.2f, count: %u\n",
kono
parents:
diff changeset
3284 non_singular_classes_count ? 1.0f * non_singular_classes_sum /
kono
parents:
diff changeset
3285 non_singular_classes_count : 0.0f,
kono
parents:
diff changeset
3286 non_singular_classes_count);
kono
parents:
diff changeset
3287 fprintf (dump_file, "Equal symbols: %u\n", equal_items);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3288 unsigned total = equal_items + non_singular_classes_count;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3289 fprintf (dump_file, "Totally needed symbols: %u"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3290 ", fraction of loaded symbols: %.2f%%\n\n", total,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3291 loaded_symbols ? 100.0f * total / loaded_symbols: 0.0f);
111
kono
parents:
diff changeset
3292 }
kono
parents:
diff changeset
3293
kono
parents:
diff changeset
3294 unsigned int l;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3295 std::pair<congruence_class_group *, int> *it;
111
kono
parents:
diff changeset
3296 FOR_EACH_VEC_ELT (classes, l, it)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3297 for (unsigned int i = 0; i < it->first->classes.length (); i++)
111
kono
parents:
diff changeset
3298 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3299 congruence_class *c = it->first->classes[i];
111
kono
parents:
diff changeset
3300
kono
parents:
diff changeset
3301 if (c->members.length () == 1)
kono
parents:
diff changeset
3302 continue;
kono
parents:
diff changeset
3303
kono
parents:
diff changeset
3304 sem_item *source = c->members[0];
kono
parents:
diff changeset
3305
kono
parents:
diff changeset
3306 if (DECL_NAME (source->decl)
kono
parents:
diff changeset
3307 && MAIN_NAME_P (DECL_NAME (source->decl)))
kono
parents:
diff changeset
3308 /* If merge via wrappers, picking main as the target can be
kono
parents:
diff changeset
3309 problematic. */
kono
parents:
diff changeset
3310 source = c->members[1];
kono
parents:
diff changeset
3311
kono
parents:
diff changeset
3312 for (unsigned int j = 0; j < c->members.length (); j++)
kono
parents:
diff changeset
3313 {
kono
parents:
diff changeset
3314 sem_item *alias = c->members[j];
kono
parents:
diff changeset
3315
kono
parents:
diff changeset
3316 if (alias == source)
kono
parents:
diff changeset
3317 continue;
kono
parents:
diff changeset
3318
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3319 dump_user_location_t loc
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3320 = dump_user_location_t::from_function_decl (source->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3321 if (dump_enabled_p ())
111
kono
parents:
diff changeset
3322 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3323 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3324 "Semantic equality hit:%s->%s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3325 source->node->dump_name (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3326 alias->node->dump_name ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3327 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3328 "Assembler symbol names:%s->%s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3329 source->node->dump_asm_name (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3330 alias->node->dump_asm_name ());
111
kono
parents:
diff changeset
3331 }
kono
parents:
diff changeset
3332
kono
parents:
diff changeset
3333 if (lookup_attribute ("no_icf", DECL_ATTRIBUTES (alias->decl)))
kono
parents:
diff changeset
3334 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3335 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3336 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3337 "Merge operation is skipped due to no_icf "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3338 "attribute.\n");
111
kono
parents:
diff changeset
3339 continue;
kono
parents:
diff changeset
3340 }
kono
parents:
diff changeset
3341
kono
parents:
diff changeset
3342 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3343 {
kono
parents:
diff changeset
3344 source->dump_to_file (dump_file);
kono
parents:
diff changeset
3345 alias->dump_to_file (dump_file);
kono
parents:
diff changeset
3346 }
kono
parents:
diff changeset
3347
kono
parents:
diff changeset
3348 if (dbg_cnt (merged_ipa_icf))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3349 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3350 bool merged = source->merge (alias);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3351 merged_p |= merged;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3352
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3353 if (merged && alias->type == VAR)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3354 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3355 symtab_pair p = symtab_pair (source->node, alias->node);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3356 m_merged_variables.safe_push (p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3357 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3358 }
111
kono
parents:
diff changeset
3359 }
kono
parents:
diff changeset
3360 }
kono
parents:
diff changeset
3361
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3362 if (!m_merged_variables.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3363 fixup_points_to_sets ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3364
111
kono
parents:
diff changeset
3365 return merged_p;
kono
parents:
diff changeset
3366 }
kono
parents:
diff changeset
3367
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3368 /* Fixup points to set PT. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3369
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3370 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3371 sem_item_optimizer::fixup_pt_set (struct pt_solution *pt)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3372 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3373 if (pt->vars == NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3374 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3375
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3376 unsigned i;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3377 symtab_pair *item;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3378 FOR_EACH_VEC_ELT (m_merged_variables, i, item)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3379 if (bitmap_bit_p (pt->vars, DECL_UID (item->second->decl)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3380 bitmap_set_bit (pt->vars, DECL_UID (item->first->decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3381 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3382
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3383 /* Set all points-to UIDs of aliases pointing to node N as UID. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3384
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3385 static void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3386 set_alias_uids (symtab_node *n, int uid)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3387 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3388 ipa_ref *ref;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3389 FOR_EACH_ALIAS (n, ref)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3390 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3391 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3392 fprintf (dump_file, " Setting points-to UID of [%s] as %d\n",
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3393 ref->referring->dump_asm_name (), uid);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3394
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3395 SET_DECL_PT_UID (ref->referring->decl, uid);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3396 set_alias_uids (ref->referring, uid);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3397 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3398 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3399
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3400 /* Fixup points to analysis info. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3401
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3402 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3403 sem_item_optimizer::fixup_points_to_sets (void)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3404 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3405 /* TODO: remove in GCC 9 and trigger PTA re-creation after IPA passes. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3406 cgraph_node *cnode;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3407
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3408 FOR_EACH_DEFINED_FUNCTION (cnode)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3409 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3410 tree name;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3411 unsigned i;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3412 function *fn = DECL_STRUCT_FUNCTION (cnode->decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3413 if (!gimple_in_ssa_p (fn))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3414 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3415
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3416 FOR_EACH_SSA_NAME (i, name, fn)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3417 if (POINTER_TYPE_P (TREE_TYPE (name))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3418 && SSA_NAME_PTR_INFO (name))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3419 fixup_pt_set (&SSA_NAME_PTR_INFO (name)->pt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3420 fixup_pt_set (&fn->gimple_df->escaped);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3421
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3422 /* The above gets us to 99% I guess, at least catching the
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3423 address compares. Below also gets us aliasing correct
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3424 but as said we're giving leeway to the situation with
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3425 readonly vars anyway, so ... */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3426 basic_block bb;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3427 FOR_EACH_BB_FN (bb, fn)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3428 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3429 gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3430 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3431 gcall *call = dyn_cast<gcall *> (gsi_stmt (gsi));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3432 if (call)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3433 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3434 fixup_pt_set (gimple_call_use_set (call));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3435 fixup_pt_set (gimple_call_clobber_set (call));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3436 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3437 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3438 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3439
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3440 unsigned i;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3441 symtab_pair *item;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3442 FOR_EACH_VEC_ELT (m_merged_variables, i, item)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3443 set_alias_uids (item->first, DECL_UID (item->first->decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3444 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3445
111
kono
parents:
diff changeset
3446 /* Dump function prints all class members to a FILE with an INDENT. */
kono
parents:
diff changeset
3447
kono
parents:
diff changeset
3448 void
kono
parents:
diff changeset
3449 congruence_class::dump (FILE *file, unsigned int indent) const
kono
parents:
diff changeset
3450 {
kono
parents:
diff changeset
3451 FPRINTF_SPACES (file, indent, "class with id: %u, hash: %u, items: %u\n",
kono
parents:
diff changeset
3452 id, members[0]->get_hash (), members.length ());
kono
parents:
diff changeset
3453
kono
parents:
diff changeset
3454 FPUTS_SPACES (file, indent + 2, "");
kono
parents:
diff changeset
3455 for (unsigned i = 0; i < members.length (); i++)
kono
parents:
diff changeset
3456 fprintf (file, "%s ", members[i]->node->dump_asm_name ());
kono
parents:
diff changeset
3457
kono
parents:
diff changeset
3458 fprintf (file, "\n");
kono
parents:
diff changeset
3459 }
kono
parents:
diff changeset
3460
kono
parents:
diff changeset
3461 /* Returns true if there's a member that is used from another group. */
kono
parents:
diff changeset
3462
kono
parents:
diff changeset
3463 bool
kono
parents:
diff changeset
3464 congruence_class::is_class_used (void)
kono
parents:
diff changeset
3465 {
kono
parents:
diff changeset
3466 for (unsigned int i = 0; i < members.length (); i++)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3467 if (members[i]->referenced_by_count)
111
kono
parents:
diff changeset
3468 return true;
kono
parents:
diff changeset
3469
kono
parents:
diff changeset
3470 return false;
kono
parents:
diff changeset
3471 }
kono
parents:
diff changeset
3472
kono
parents:
diff changeset
3473 /* Generate pass summary for IPA ICF pass. */
kono
parents:
diff changeset
3474
kono
parents:
diff changeset
3475 static void
kono
parents:
diff changeset
3476 ipa_icf_generate_summary (void)
kono
parents:
diff changeset
3477 {
kono
parents:
diff changeset
3478 if (!optimizer)
kono
parents:
diff changeset
3479 optimizer = new sem_item_optimizer ();
kono
parents:
diff changeset
3480
kono
parents:
diff changeset
3481 optimizer->register_hooks ();
kono
parents:
diff changeset
3482 optimizer->parse_funcs_and_vars ();
kono
parents:
diff changeset
3483 }
kono
parents:
diff changeset
3484
kono
parents:
diff changeset
3485 /* Write pass summary for IPA ICF pass. */
kono
parents:
diff changeset
3486
kono
parents:
diff changeset
3487 static void
kono
parents:
diff changeset
3488 ipa_icf_write_summary (void)
kono
parents:
diff changeset
3489 {
kono
parents:
diff changeset
3490 gcc_assert (optimizer);
kono
parents:
diff changeset
3491
kono
parents:
diff changeset
3492 optimizer->write_summary ();
kono
parents:
diff changeset
3493 }
kono
parents:
diff changeset
3494
kono
parents:
diff changeset
3495 /* Read pass summary for IPA ICF pass. */
kono
parents:
diff changeset
3496
kono
parents:
diff changeset
3497 static void
kono
parents:
diff changeset
3498 ipa_icf_read_summary (void)
kono
parents:
diff changeset
3499 {
kono
parents:
diff changeset
3500 if (!optimizer)
kono
parents:
diff changeset
3501 optimizer = new sem_item_optimizer ();
kono
parents:
diff changeset
3502
kono
parents:
diff changeset
3503 optimizer->read_summary ();
kono
parents:
diff changeset
3504 optimizer->register_hooks ();
kono
parents:
diff changeset
3505 }
kono
parents:
diff changeset
3506
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3507 /* Semantic equality execution function. */
111
kono
parents:
diff changeset
3508
kono
parents:
diff changeset
3509 static unsigned int
kono
parents:
diff changeset
3510 ipa_icf_driver (void)
kono
parents:
diff changeset
3511 {
kono
parents:
diff changeset
3512 gcc_assert (optimizer);
kono
parents:
diff changeset
3513
kono
parents:
diff changeset
3514 bool merged_p = optimizer->execute ();
kono
parents:
diff changeset
3515
kono
parents:
diff changeset
3516 delete optimizer;
kono
parents:
diff changeset
3517 optimizer = NULL;
kono
parents:
diff changeset
3518
kono
parents:
diff changeset
3519 return merged_p ? TODO_remove_functions : 0;
kono
parents:
diff changeset
3520 }
kono
parents:
diff changeset
3521
kono
parents:
diff changeset
3522 const pass_data pass_data_ipa_icf =
kono
parents:
diff changeset
3523 {
kono
parents:
diff changeset
3524 IPA_PASS, /* type */
kono
parents:
diff changeset
3525 "icf", /* name */
kono
parents:
diff changeset
3526 OPTGROUP_IPA, /* optinfo_flags */
kono
parents:
diff changeset
3527 TV_IPA_ICF, /* tv_id */
kono
parents:
diff changeset
3528 0, /* properties_required */
kono
parents:
diff changeset
3529 0, /* properties_provided */
kono
parents:
diff changeset
3530 0, /* properties_destroyed */
kono
parents:
diff changeset
3531 0, /* todo_flags_start */
kono
parents:
diff changeset
3532 0, /* todo_flags_finish */
kono
parents:
diff changeset
3533 };
kono
parents:
diff changeset
3534
kono
parents:
diff changeset
3535 class pass_ipa_icf : public ipa_opt_pass_d
kono
parents:
diff changeset
3536 {
kono
parents:
diff changeset
3537 public:
kono
parents:
diff changeset
3538 pass_ipa_icf (gcc::context *ctxt)
kono
parents:
diff changeset
3539 : ipa_opt_pass_d (pass_data_ipa_icf, ctxt,
kono
parents:
diff changeset
3540 ipa_icf_generate_summary, /* generate_summary */
kono
parents:
diff changeset
3541 ipa_icf_write_summary, /* write_summary */
kono
parents:
diff changeset
3542 ipa_icf_read_summary, /* read_summary */
kono
parents:
diff changeset
3543 NULL, /*
kono
parents:
diff changeset
3544 write_optimization_summary */
kono
parents:
diff changeset
3545 NULL, /*
kono
parents:
diff changeset
3546 read_optimization_summary */
kono
parents:
diff changeset
3547 NULL, /* stmt_fixup */
kono
parents:
diff changeset
3548 0, /* function_transform_todo_flags_start */
kono
parents:
diff changeset
3549 NULL, /* function_transform */
kono
parents:
diff changeset
3550 NULL) /* variable_transform */
kono
parents:
diff changeset
3551 {}
kono
parents:
diff changeset
3552
kono
parents:
diff changeset
3553 /* opt_pass methods: */
kono
parents:
diff changeset
3554 virtual bool gate (function *)
kono
parents:
diff changeset
3555 {
kono
parents:
diff changeset
3556 return in_lto_p || flag_ipa_icf_variables || flag_ipa_icf_functions;
kono
parents:
diff changeset
3557 }
kono
parents:
diff changeset
3558
kono
parents:
diff changeset
3559 virtual unsigned int execute (function *)
kono
parents:
diff changeset
3560 {
kono
parents:
diff changeset
3561 return ipa_icf_driver();
kono
parents:
diff changeset
3562 }
kono
parents:
diff changeset
3563 }; // class pass_ipa_icf
kono
parents:
diff changeset
3564
kono
parents:
diff changeset
3565 } // ipa_icf namespace
kono
parents:
diff changeset
3566
kono
parents:
diff changeset
3567 ipa_opt_pass_d *
kono
parents:
diff changeset
3568 make_pass_ipa_icf (gcc::context *ctxt)
kono
parents:
diff changeset
3569 {
kono
parents:
diff changeset
3570 return new ipa_icf::pass_ipa_icf (ctxt);
kono
parents:
diff changeset
3571 }