gcc80: Handle TZ specific "%+" format in strftime.
[dragonfly.git] / contrib / gcc-8.0 / gcc / ipa-comdats.c
1 /* Localize comdats.
2    Copyright (C) 2014-2018 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 /* This is very simple pass that looks for static symbols that are used
21    exlusively by symbol within one comdat group.  In this case it makes
22    sense to bring the symbol itself into the group to avoid dead code
23    that would arrise when the comdat group from current unit is replaced
24    by a different copy.  Consider for example:
25
26     static int q(void)
27     {
28       ....
29     }
30     inline int t(void)
31     {
32       return q();
33     }
34
35    if Q is used only by T, it makes sense to put Q into T's comdat group.
36
37    The pass solve simple dataflow across the callgraph trying to prove what
38    symbols are used exclusively from a given comdat group.
39
40    The implementation maintains a queue linked by AUX pointer terminated by
41    pointer value 1. Lattice values are NULL for TOP, actual comdat group, or
42    ERROR_MARK_NODE for bottom.
43
44    TODO: When symbol is used only by comdat symbols, but from different groups,
45    it would make sense to produce a new comdat group for it with anonymous name.
46
47    TODO2: We can't mix variables and functions within one group.  Currently
48    we just give up on references of symbols of different types.  We also should
49    handle this by anonymous comdat group section.  */
50
51 #include "config.h"
52 #include "system.h"
53 #include "coretypes.h"
54 #include "tm.h"
55 #include "tree.h"
56 #include "tree-pass.h"
57 #include "cgraph.h"
58
59 /* Main dataflow loop propagating comdat groups across
60    the symbol table.  All references to SYMBOL are examined
61    and NEWGROUP is updated accordingly. MAP holds current lattice
62    values for individual symbols.  */
63
64 tree
65 propagate_comdat_group (struct symtab_node *symbol,
66                         tree newgroup, hash_map<symtab_node *, tree> &map)
67 {
68   int i;
69   struct ipa_ref *ref;
70
71   /* Walk all references to SYMBOL, recursively dive into aliases.  */
72
73   for (i = 0;
74        symbol->iterate_referring (i, ref)
75        && newgroup != error_mark_node; i++)
76     {
77       struct symtab_node *symbol2 = ref->referring;
78
79       if (ref->use == IPA_REF_ALIAS)
80         {
81           newgroup = propagate_comdat_group (symbol2, newgroup, map);
82           continue;
83         }
84
85       /* One COMDAT group can not hold both variables and functions at
86          a same time.  For now we just go to BOTTOM, in future we may
87          invent special comdat groups for this case.  */
88
89       if (symbol->type != symbol2->type)
90         {
91           newgroup = error_mark_node;
92           break;
93         }
94
95       /* If we see inline clone, its comdat group actually
96          corresponds to the comdat group of the function it is inlined
97          to.  */
98
99       if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
100         {
101           if (cn->global.inlined_to)
102             symbol2 = cn->global.inlined_to;
103         }
104
105       /* The actual merge operation.  */
106
107       tree *val2 = map.get (symbol2);
108
109       if (val2 && *val2 != newgroup)
110         {
111           if (!newgroup)
112             newgroup = *val2;
113           else
114             newgroup = error_mark_node;
115         }
116     }
117
118   /* If we analyze function, walk also callers.  */
119
120   cgraph_node *cnode = dyn_cast <cgraph_node *> (symbol);
121
122   if (cnode)
123     for (struct cgraph_edge * edge = cnode->callers;
124          edge && newgroup != error_mark_node; edge = edge->next_caller)
125       {
126         struct symtab_node *symbol2 = edge->caller;
127
128         if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
129           {
130             /* Thunks can not call across section boundary.  */
131             if (cn->thunk.thunk_p)
132               newgroup = propagate_comdat_group (symbol2, newgroup, map);
133             /* If we see inline clone, its comdat group actually
134                corresponds to the comdat group of the function it
135                is inlined to.  */
136             if (cn->global.inlined_to)
137               symbol2 = cn->global.inlined_to;
138           }
139
140         /* The actual merge operation.  */
141
142         tree *val2 = map.get (symbol2);
143
144         if (val2 && *val2 != newgroup)
145           {
146             if (!newgroup)
147               newgroup = *val2;
148             else
149               newgroup = error_mark_node;
150           }
151       }
152   return newgroup;
153 }
154
155
156 /* Add all references of SYMBOL that are defined into queue started by FIRST
157    and linked by AUX pointer (unless they are already enqueued).
158    Walk recursively inlined functions.  */
159
160 void
161 enqueue_references (symtab_node **first,
162                     symtab_node *symbol)
163 {
164   int i;
165   struct ipa_ref *ref = NULL;
166
167   for (i = 0; symbol->iterate_reference (i, ref); i++)
168     {
169       symtab_node *node = ref->referred->ultimate_alias_target ();
170
171       /* Always keep thunks in same sections as target function.  */
172       if (is_a <cgraph_node *>(node))
173         node = dyn_cast <cgraph_node *> (node)->function_symbol ();
174       if (!node->aux && node->definition)
175         {
176            node->aux = *first;
177            *first = node;
178         }
179     }
180
181   if (cgraph_node *cnode = dyn_cast <cgraph_node *> (symbol))
182     {
183       struct cgraph_edge *edge;
184
185       for (edge = cnode->callees; edge; edge = edge->next_callee)
186         if (!edge->inline_failed)
187           enqueue_references (first, edge->callee);
188         else
189           {
190             symtab_node *node = edge->callee->ultimate_alias_target ();
191
192             /* Always keep thunks in same sections as target function.  */
193             if (is_a <cgraph_node *>(node))
194               node = dyn_cast <cgraph_node *> (node)->function_symbol ();
195             if (!node->aux && node->definition)
196               {
197                  node->aux = *first;
198                  *first = node;
199               }
200           }
201     }
202 }
203
204 /* Set comdat group of SYMBOL to GROUP.
205    Callback for for_node_and_aliases.  */
206
207 bool
208 set_comdat_group (symtab_node *symbol,
209                   void *head_p)
210 {
211   symtab_node *head = (symtab_node *)head_p;
212
213   gcc_assert (!symbol->get_comdat_group ());
214   if (symbol->real_symbol_p ())
215     {
216       symbol->set_comdat_group (head->get_comdat_group ());
217       symbol->add_to_same_comdat_group (head);
218     }
219   return false;
220 }
221
222 /* Set comdat group of SYMBOL to GROUP.
223    Callback for for_node_thunks_and_aliases.  */
224
225 bool
226 set_comdat_group_1 (cgraph_node *symbol,
227                     void *head_p)
228 {
229   return set_comdat_group (symbol, head_p);
230 }
231
232 /* The actual pass with the main dataflow loop.  */
233
234 static unsigned int
235 ipa_comdats (void)
236 {
237   hash_map<symtab_node *, tree> map (251);
238   hash_map<tree, symtab_node *> comdat_head_map (251);
239   symtab_node *symbol;
240   bool comdat_group_seen = false;
241   symtab_node *first = (symtab_node *) (void *) 1;
242   tree group;
243
244   /* Start the dataflow by assigning comdat group to symbols that are in comdat
245      groups already.  All other externally visible symbols must stay, we use
246      ERROR_MARK_NODE as bottom for the propagation.  */
247
248   FOR_EACH_DEFINED_SYMBOL (symbol)
249     if (!symbol->real_symbol_p ())
250       ;
251     else if ((group = symbol->get_comdat_group ()) != NULL)
252       {
253         map.put (symbol, group);
254         comdat_head_map.put (group, symbol);
255         comdat_group_seen = true;
256
257         /* Mark the symbol so we won't waste time visiting it for dataflow.  */
258         symbol->aux = (symtab_node *) (void *) 1;
259       }
260     /* See symbols that can not be privatized to comdats; that is externally
261        visible symbols or otherwise used ones.  We also do not want to mangle
262        user section names.  */
263     else if (symbol->externally_visible
264              || symbol->force_output
265              || symbol->used_from_other_partition
266              || TREE_THIS_VOLATILE (symbol->decl)
267              || symbol->get_section ()
268              || (TREE_CODE (symbol->decl) == FUNCTION_DECL
269                  && (DECL_STATIC_CONSTRUCTOR (symbol->decl)
270                      || DECL_STATIC_DESTRUCTOR (symbol->decl))))
271       {
272         symtab_node *target = symbol->ultimate_alias_target ();
273
274         /* Always keep thunks in same sections as target function.  */
275         if (is_a <cgraph_node *>(target))
276           target = dyn_cast <cgraph_node *> (target)->function_symbol ();
277         map.put (target, error_mark_node);
278
279         /* Mark the symbol so we won't waste time visiting it for dataflow.  */
280         symbol->aux = (symtab_node *) (void *) 1;
281       }
282     else
283       {
284         /* Enqueue symbol for dataflow.  */
285         symbol->aux = first;
286         first = symbol;
287       }
288
289   if (!comdat_group_seen)
290     {
291       FOR_EACH_DEFINED_SYMBOL (symbol)
292         symbol->aux = NULL;
293       return 0;
294     }
295
296   /* The actual dataflow.  */
297
298   while (first != (void *) 1)
299     {
300       tree group = NULL;
301       tree newgroup, *val;
302
303       symbol = first;
304       first = (symtab_node *)first->aux;
305
306       /* Get current lattice value of SYMBOL.  */
307       val = map.get (symbol);
308       if (val)
309         group = *val;
310
311       /* If it is bottom, there is nothing to do; do not clear AUX
312          so we won't re-queue the symbol.  */
313       if (group == error_mark_node)
314         continue;
315
316       newgroup = propagate_comdat_group (symbol, group, map);
317
318       /* If nothing changed, proceed to next symbol.  */
319       if (newgroup == group)
320         {
321           symbol->aux = NULL;
322           continue;
323         }
324
325       /* Update lattice value and enqueue all references for re-visiting.  */
326       gcc_assert (newgroup);
327       if (val)
328         *val = newgroup;
329       else
330         map.put (symbol, newgroup);
331       enqueue_references (&first, symbol);
332
333       /* We may need to revisit the symbol unless it is BOTTOM.  */
334       if (newgroup != error_mark_node)
335         symbol->aux = NULL;
336     }
337
338   /* Finally assign symbols to the sections.  */
339
340   FOR_EACH_DEFINED_SYMBOL (symbol)
341     {
342       struct cgraph_node *fun;
343       symbol->aux = NULL; 
344       if (!symbol->get_comdat_group ()
345           && !symbol->alias
346           && (!(fun = dyn_cast <cgraph_node *> (symbol))
347               || !fun->thunk.thunk_p)
348           && symbol->real_symbol_p ())
349         {
350           tree *val = map.get (symbol);
351
352           /* A NULL here means that SYMBOL is unreachable in the definition
353              of ipa-comdats. Either ipa-comdats is wrong about this or someone
354              forgot to cleanup and remove unreachable functions earlier.  */
355           gcc_assert (val);
356
357           tree group = *val;
358
359           if (group == error_mark_node)
360             continue;
361           if (dump_file)
362             {
363               fprintf (dump_file, "Localizing symbol\n");
364               symbol->dump (dump_file);
365               fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group));
366             }
367           if (is_a <cgraph_node *> (symbol))
368            dyn_cast <cgraph_node *>(symbol)->call_for_symbol_thunks_and_aliases
369                   (set_comdat_group_1,
370                    *comdat_head_map.get (group),
371                    true);
372           else
373            symbol->call_for_symbol_and_aliases
374                   (set_comdat_group,
375                    *comdat_head_map.get (group),
376                    true);
377         }
378     }
379   return 0;
380 }
381
382 namespace {
383
384 const pass_data pass_data_ipa_comdats =
385 {
386   IPA_PASS, /* type */
387   "comdats", /* name */
388   OPTGROUP_NONE, /* optinfo_flags */
389   TV_IPA_COMDATS, /* tv_id */
390   0, /* properties_required */
391   0, /* properties_provided */
392   0, /* properties_destroyed */
393   0, /* todo_flags_start */
394   0, /* todo_flags_finish */
395 };
396
397 class pass_ipa_comdats : public ipa_opt_pass_d
398 {
399 public:
400   pass_ipa_comdats (gcc::context *ctxt)
401     : ipa_opt_pass_d (pass_data_ipa_comdats, ctxt,
402                       NULL, /* generate_summary */
403                       NULL, /* write_summary */
404                       NULL, /* read_summary */
405                       NULL, /* write_optimization_summary */
406                       NULL, /* read_optimization_summary */
407                       NULL, /* stmt_fixup */
408                       0, /* function_transform_todo_flags_start */
409                       NULL, /* function_transform */
410                       NULL) /* variable_transform */
411   {}
412
413   /* opt_pass methods: */
414   virtual bool gate (function *);
415   virtual unsigned int execute (function *) { return ipa_comdats (); }
416
417 }; // class pass_ipa_comdats
418
419 bool
420 pass_ipa_comdats::gate (function *)
421 {
422   return HAVE_COMDAT_GROUP;
423 }
424
425 } // anon namespace
426
427 ipa_opt_pass_d *
428 make_pass_ipa_comdats (gcc::context *ctxt)
429 {
430   return new pass_ipa_comdats (ctxt);
431 }