Mercurial > hg > CbC > CbC_gcc
annotate gcc/ipa.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 |
rev | line source |
---|---|
0 | 1 /* Basic IPA optimizations and utilities. |
145 | 2 Copyright (C) 2003-2020 Free Software Foundation, Inc. |
0 | 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 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
111 | 23 #include "backend.h" |
24 #include "target.h" | |
25 #include "tree.h" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
26 #include "gimple.h" |
111 | 27 #include "alloc-pool.h" |
28 #include "tree-pass.h" | |
29 #include "stringpool.h" | |
30 #include "cgraph.h" | |
31 #include "gimplify.h" | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
32 #include "tree-iterator.h" |
111 | 33 #include "ipa-utils.h" |
34 #include "symbol-summary.h" | |
35 #include "tree-vrp.h" | |
36 #include "ipa-prop.h" | |
37 #include "ipa-fnsummary.h" | |
38 #include "dbgcnt.h" | |
39 #include "debug.h" | |
40 #include "stringpool.h" | |
41 #include "attribs.h" | |
0 | 42 |
111 | 43 /* Return true when NODE has ADDR reference. */ |
44 | |
45 static bool | |
46 has_addr_references_p (struct cgraph_node *node, | |
47 void *) | |
48 { | |
49 int i; | |
50 struct ipa_ref *ref = NULL; | |
51 | |
52 for (i = 0; node->iterate_referring (i, ref); i++) | |
53 if (ref->use == IPA_REF_ADDR) | |
54 return true; | |
55 return false; | |
56 } | |
57 | |
58 /* Return true when NODE can be target of an indirect call. */ | |
59 | |
60 static bool | |
61 is_indirect_call_target_p (struct cgraph_node *node, void *) | |
62 { | |
63 return node->indirect_call_target; | |
0 | 64 } |
65 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
66 /* Look for all functions inlined to NODE and update their inlined_to pointers |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
67 to INLINED_TO. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
68 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
69 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
70 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
71 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
72 struct cgraph_edge *e; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
73 for (e = node->callees; e; e = e->next_callee) |
145 | 74 if (e->callee->inlined_to) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
75 { |
145 | 76 e->callee->inlined_to = inlined_to; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
77 update_inlined_to_pointer (e->callee, inlined_to); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
78 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
79 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
80 |
111 | 81 /* Add symtab NODE to queue starting at FIRST. |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
82 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
83 The queue is linked via AUX pointers and terminated by pointer to 1. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
84 We enqueue nodes at two occasions: when we find them reachable or when we find |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
85 their bodies needed for further clonning. In the second case we mark them |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
86 by pointer to 2 after processing so they are re-queue when they become |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
87 reachable. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
88 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
89 static void |
111 | 90 enqueue_node (symtab_node *node, symtab_node **first, |
91 hash_set<symtab_node *> *reachable) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
92 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
93 /* Node is still in queue; do nothing. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
94 if (node->aux && node->aux != (void *) 2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
95 return; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
96 /* Node was already processed as unreachable, re-enqueue |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
97 only if it became reachable now. */ |
111 | 98 if (node->aux == (void *)2 && !reachable->contains (node)) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
99 return; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
100 node->aux = *first; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
101 *first = node; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
102 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
103 |
145 | 104 /* Return true if NODE may get inlined later. |
105 This is used to keep DECL_EXTERNAL function bodies around long enough | |
106 so inliner can proces them. */ | |
107 | |
108 static bool | |
109 possible_inline_candidate_p (symtab_node *node) | |
110 { | |
111 if (symtab->state >= IPA_SSA_AFTER_INLINING) | |
112 return false; | |
113 cgraph_node *cnode = dyn_cast <cgraph_node *> (node); | |
114 if (!cnode) | |
115 return false; | |
116 if (DECL_UNINLINABLE (cnode->decl)) | |
117 return false; | |
118 if (opt_for_fn (cnode->decl, optimize)) | |
119 return true; | |
120 if (symtab->state >= IPA_SSA) | |
121 return false; | |
122 return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl)); | |
123 } | |
124 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
125 /* Process references. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
126 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
127 static void |
111 | 128 process_references (symtab_node *snode, |
129 symtab_node **first, | |
130 hash_set<symtab_node *> *reachable) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
131 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
132 int i; |
111 | 133 struct ipa_ref *ref = NULL; |
134 for (i = 0; snode->iterate_reference (i, ref); i++) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
135 { |
111 | 136 symtab_node *node = ref->referred; |
137 symtab_node *body = node->ultimate_alias_target (); | |
138 | |
139 if (node->definition && !node->in_other_partition | |
140 && ((!DECL_EXTERNAL (node->decl) || node->alias) | |
145 | 141 || (possible_inline_candidate_p (node) |
111 | 142 /* We use variable constructors during late compilation for |
143 constant folding. Keep references alive so partitioning | |
144 knows about potential references. */ | |
145 || (VAR_P (node->decl) | |
131 | 146 && (flag_wpa |
147 || flag_incremental_link | |
148 == INCREMENTAL_LINK_LTO) | |
149 && dyn_cast <varpool_node *> (node) | |
150 ->ctor_useable_for_folding_p ())))) | |
111 | 151 { |
152 /* Be sure that we will not optimize out alias target | |
153 body. */ | |
154 if (DECL_EXTERNAL (node->decl) | |
155 && node->alias | |
145 | 156 && symtab->state < IPA_SSA_AFTER_INLINING) |
111 | 157 reachable->add (body); |
158 reachable->add (node); | |
159 } | |
160 enqueue_node (node, first, reachable); | |
161 } | |
162 } | |
163 | |
164 /* EDGE is an polymorphic call. If BEFORE_INLINING_P is set, mark | |
165 all its potential targets as reachable to permit later inlining if | |
166 devirtualization happens. After inlining still keep their declarations | |
167 around, so we can devirtualize to a direct call. | |
168 | |
169 Also try to make trivial devirutalization when no or only one target is | |
170 possible. */ | |
171 | |
172 static void | |
173 walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, | |
174 struct cgraph_edge *edge, | |
175 symtab_node **first, | |
145 | 176 hash_set<symtab_node *> *reachable) |
111 | 177 { |
178 unsigned int i; | |
179 void *cache_token; | |
180 bool final; | |
181 vec <cgraph_node *>targets | |
182 = possible_polymorphic_call_targets | |
183 (edge, &final, &cache_token); | |
184 | |
185 if (!reachable_call_targets->add (cache_token)) | |
186 { | |
187 for (i = 0; i < targets.length (); i++) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
188 { |
111 | 189 struct cgraph_node *n = targets[i]; |
190 | |
191 /* Do not bother to mark virtual methods in anonymous namespace; | |
192 either we will find use of virtual table defining it, or it is | |
193 unused. */ | |
194 if (TREE_CODE (TREE_TYPE (n->decl)) == METHOD_TYPE | |
195 && type_in_anonymous_namespace_p | |
196 (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl)))) | |
197 continue; | |
198 | |
199 n->indirect_call_target = true; | |
200 symtab_node *body = n->function_symbol (); | |
201 | |
202 /* Prior inlining, keep alive bodies of possible targets for | |
203 devirtualization. */ | |
204 if (n->definition | |
145 | 205 && (possible_inline_candidate_p (body) |
111 | 206 && opt_for_fn (body->decl, flag_devirtualize))) |
207 { | |
208 /* Be sure that we will not optimize out alias target | |
209 body. */ | |
210 if (DECL_EXTERNAL (n->decl) | |
211 && n->alias | |
145 | 212 && symtab->state < IPA_SSA_AFTER_INLINING) |
111 | 213 reachable->add (body); |
214 reachable->add (n); | |
215 } | |
216 /* Even after inlining we want to keep the possible targets in the | |
217 boundary, so late passes can still produce direct call even if | |
218 the chance for inlining is lost. */ | |
219 enqueue_node (n, first, reachable); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
220 } |
111 | 221 } |
222 | |
223 /* Very trivial devirtualization; when the type is | |
224 final or anonymous (so we know all its derivation) | |
225 and there is only one possible virtual call target, | |
226 make the edge direct. */ | |
227 if (final) | |
228 { | |
229 if (targets.length () <= 1 && dbg_cnt (devirt)) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
230 { |
111 | 231 cgraph_node *target, *node = edge->caller; |
232 if (targets.length () == 1) | |
233 target = targets[0]; | |
234 else | |
235 target = cgraph_node::get_create | |
236 (builtin_decl_implicit (BUILT_IN_UNREACHABLE)); | |
237 | |
238 if (dump_enabled_p ()) | |
131 | 239 { |
240 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt, | |
111 | 241 "devirtualizing call in %s to %s\n", |
242 edge->caller->dump_name (), | |
243 target->dump_name ()); | |
244 } | |
145 | 245 edge = cgraph_edge::make_direct (edge, target); |
111 | 246 if (ipa_fn_summaries) |
145 | 247 ipa_update_overall_fn_summary (node->inlined_to |
248 ? node->inlined_to : node); | |
111 | 249 else if (edge->call_stmt) |
145 | 250 cgraph_edge::redirect_call_stmt_to_callee (edge); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
251 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
252 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
253 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
254 |
111 | 255 /* Perform reachability analysis and reclaim all unreachable nodes. |
256 | |
257 The algorithm is basically mark&sweep but with some extra refinements: | |
258 | |
259 - reachable extern inline functions needs special handling; the bodies needs | |
260 to stay in memory until inlining in hope that they will be inlined. | |
261 After inlining we release their bodies and turn them into unanalyzed | |
262 nodes even when they are reachable. | |
263 | |
264 - virtual functions are kept in callgraph even if they seem unreachable in | |
265 hope calls to them will be devirtualized. | |
266 | |
267 Again we remove them after inlining. In late optimization some | |
268 devirtualization may happen, but it is not important since we won't inline | |
269 the call. In theory early opts and IPA should work out all important cases. | |
270 | |
271 - virtual clones needs bodies of their origins for later materialization; | |
272 this means that we want to keep the body even if the origin is unreachable | |
273 otherwise. To avoid origin from sitting in the callgraph and being | |
274 walked by IPA passes, we turn them into unanalyzed nodes with body | |
275 defined. | |
276 | |
277 We maintain set of function declaration where body needs to stay in | |
278 body_needed_for_clonning | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
279 |
111 | 280 Inline clones represent special case: their declaration match the |
281 declaration of origin and cgraph_remove_node already knows how to | |
282 reshape callgraph and preserve body when offline copy of function or | |
283 inline clone is being removed. | |
284 | |
285 - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL | |
286 variables with DECL_INITIAL set. We finalize these and keep reachable | |
287 ones around for constant folding purposes. After inlining we however | |
288 stop walking their references to let everything static referneced by them | |
289 to be removed when it is otherwise unreachable. | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
290 |
111 | 291 We maintain queue of both reachable symbols (i.e. defined symbols that needs |
292 to stay) and symbols that are in boundary (i.e. external symbols referenced | |
293 by reachable symbols or origins of clones). The queue is represented | |
294 as linked list by AUX pointer terminated by 1. | |
295 | |
296 At the end we keep all reachable symbols. For symbols in boundary we always | |
297 turn definition into a declaration, but we may keep function body around | |
298 based on body_needed_for_clonning | |
299 | |
300 All symbols that enter the queue have AUX pointer non-zero and are in the | |
301 boundary. Pointer set REACHABLE is used to track reachable symbols. | |
302 | |
303 Every symbol can be visited twice - once as part of boundary and once | |
304 as real reachable symbol. enqueue_node needs to decide whether the | |
305 node needs to be re-queued for second processing. For this purpose | |
306 we set AUX pointer of processed symbols in the boundary to constant 2. */ | |
0 | 307 |
308 bool | |
111 | 309 symbol_table::remove_unreachable_nodes (FILE *file) |
0 | 310 { |
111 | 311 symtab_node *first = (symtab_node *) (void *) 1; |
0 | 312 struct cgraph_node *node, *next; |
111 | 313 varpool_node *vnode, *vnext; |
0 | 314 bool changed = false; |
111 | 315 hash_set<symtab_node *> reachable; |
316 hash_set<tree> body_needed_for_clonning; | |
317 hash_set<void *> reachable_call_targets; | |
0 | 318 |
111 | 319 timevar_push (TV_IPA_UNREACHABLE); |
320 build_type_inheritance_graph (); | |
0 | 321 if (file) |
322 fprintf (file, "\nReclaiming functions:"); | |
111 | 323 if (flag_checking) |
324 { | |
325 FOR_EACH_FUNCTION (node) | |
326 gcc_assert (!node->aux); | |
327 FOR_EACH_VARIABLE (vnode) | |
328 gcc_assert (!vnode->aux); | |
329 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
330 /* Mark functions whose bodies are obviously needed. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
331 This is mostly when they can be referenced externally. Inline clones |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
332 are special since their declarations are shared with master clone and thus |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
333 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */ |
111 | 334 FOR_EACH_FUNCTION (node) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
335 { |
111 | 336 node->used_as_abstract_origin = false; |
337 node->indirect_call_target = false; | |
338 if (node->definition | |
145 | 339 && !node->inlined_to |
111 | 340 && !node->in_other_partition |
341 && !node->can_remove_if_no_direct_calls_and_refs_p ()) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
342 { |
145 | 343 gcc_assert (!node->inlined_to); |
111 | 344 reachable.add (node); |
345 enqueue_node (node, &first, &reachable); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
346 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
347 else |
111 | 348 gcc_assert (!node->aux); |
349 } | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
350 |
111 | 351 /* Mark variables that are obviously needed. */ |
352 FOR_EACH_DEFINED_VARIABLE (vnode) | |
353 if (!vnode->can_remove_if_no_refs_p() | |
354 && !vnode->in_other_partition) | |
355 { | |
356 reachable.add (vnode); | |
357 enqueue_node (vnode, &first, &reachable); | |
358 } | |
359 | |
360 /* Perform reachability analysis. */ | |
361 while (first != (symtab_node *) (void *) 1) | |
0 | 362 { |
111 | 363 bool in_boundary_p = !reachable.contains (first); |
364 symtab_node *node = first; | |
365 | |
366 first = (symtab_node *)first->aux; | |
0 | 367 |
111 | 368 /* If we are processing symbol in boundary, mark its AUX pointer for |
369 possible later re-processing in enqueue_node. */ | |
370 if (in_boundary_p) | |
371 { | |
372 node->aux = (void *)2; | |
373 if (node->alias && node->analyzed) | |
374 enqueue_node (node->get_alias_target (), &first, &reachable); | |
375 } | |
376 else | |
377 { | |
378 if (TREE_CODE (node->decl) == FUNCTION_DECL | |
379 && DECL_ABSTRACT_ORIGIN (node->decl)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
380 { |
111 | 381 struct cgraph_node *origin_node |
382 = cgraph_node::get (DECL_ABSTRACT_ORIGIN (node->decl)); | |
383 if (origin_node && !origin_node->used_as_abstract_origin) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
384 { |
111 | 385 origin_node->used_as_abstract_origin = true; |
386 gcc_assert (!origin_node->prev_sibling_clone); | |
387 gcc_assert (!origin_node->next_sibling_clone); | |
388 for (cgraph_node *n = origin_node->clones; n; | |
389 n = n->next_sibling_clone) | |
390 if (n->decl == DECL_ABSTRACT_ORIGIN (node->decl)) | |
391 n->used_as_abstract_origin = true; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
392 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
393 } |
145 | 394 /* If any non-external and non-local symbol in a comdat group is |
395 reachable, force all externally visible symbols in the same comdat | |
111 | 396 group to be reachable as well. Comdat-local symbols |
397 can be discarded if all uses were inlined. */ | |
145 | 398 if (node->same_comdat_group |
399 && node->externally_visible | |
400 && !DECL_EXTERNAL (node->decl)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
401 { |
111 | 402 symtab_node *next; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
403 for (next = node->same_comdat_group; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
404 next != node; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
405 next = next->same_comdat_group) |
111 | 406 if (!next->comdat_local_p () |
145 | 407 && !DECL_EXTERNAL (next->decl) |
111 | 408 && !reachable.add (next)) |
409 enqueue_node (next, &first, &reachable); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
410 } |
111 | 411 /* Mark references as reachable. */ |
145 | 412 process_references (node, &first, &reachable); |
111 | 413 } |
414 | |
415 if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) | |
416 { | |
417 /* Mark the callees reachable unless they are direct calls to extern | |
418 inline functions we decided to not inline. */ | |
419 if (!in_boundary_p) | |
420 { | |
421 struct cgraph_edge *e; | |
422 /* Keep alive possible targets for devirtualization. */ | |
423 if (opt_for_fn (cnode->decl, optimize) | |
424 && opt_for_fn (cnode->decl, flag_devirtualize)) | |
425 { | |
426 struct cgraph_edge *next; | |
427 for (e = cnode->indirect_calls; e; e = next) | |
428 { | |
429 next = e->next_callee; | |
430 if (e->indirect_info->polymorphic) | |
431 walk_polymorphic_call_targets (&reachable_call_targets, | |
145 | 432 e, &first, &reachable); |
111 | 433 } |
434 } | |
435 for (e = cnode->callees; e; e = e->next_callee) | |
436 { | |
437 symtab_node *body = e->callee->function_symbol (); | |
438 if (e->callee->definition | |
439 && !e->callee->in_other_partition | |
440 && (!e->inline_failed | |
441 || !DECL_EXTERNAL (e->callee->decl) | |
442 || e->callee->alias | |
145 | 443 || possible_inline_candidate_p (e->callee))) |
111 | 444 { |
445 /* Be sure that we will not optimize out alias target | |
446 body. */ | |
447 if (DECL_EXTERNAL (e->callee->decl) | |
448 && e->callee->alias | |
145 | 449 && symtab->state < IPA_SSA_AFTER_INLINING) |
111 | 450 reachable.add (body); |
451 reachable.add (e->callee); | |
452 } | |
453 enqueue_node (e->callee, &first, &reachable); | |
454 } | |
455 | |
456 /* When inline clone exists, mark body to be preserved so when removing | |
457 offline copy of the function we don't kill it. */ | |
145 | 458 if (cnode->inlined_to) |
111 | 459 body_needed_for_clonning.add (cnode->decl); |
460 | |
461 /* For non-inline clones, force their origins to the boundary and ensure | |
462 that body is not removed. */ | |
463 while (cnode->clone_of) | |
464 { | |
465 bool noninline = cnode->clone_of->decl != cnode->decl; | |
466 cnode = cnode->clone_of; | |
467 if (noninline) | |
468 { | |
469 body_needed_for_clonning.add (cnode->decl); | |
470 enqueue_node (cnode, &first, &reachable); | |
471 } | |
472 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
473 |
111 | 474 } |
475 else if (cnode->thunk.thunk_p) | |
476 enqueue_node (cnode->callees->callee, &first, &reachable); | |
477 | |
478 /* If any reachable function has simd clones, mark them as | |
479 reachable as well. */ | |
480 if (cnode->simd_clones) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
481 { |
111 | 482 cgraph_node *next; |
483 for (next = cnode->simd_clones; | |
484 next; | |
485 next = next->simdclone->next_clone) | |
486 if (in_boundary_p | |
487 || !reachable.add (next)) | |
488 enqueue_node (next, &first, &reachable); | |
489 } | |
490 } | |
491 /* When we see constructor of external variable, keep referred nodes in the | |
492 boundary. This will also hold initializers of the external vars NODE | |
493 refers to. */ | |
494 varpool_node *vnode = dyn_cast <varpool_node *> (node); | |
495 if (vnode | |
496 && DECL_EXTERNAL (node->decl) | |
497 && !vnode->alias | |
498 && in_boundary_p) | |
499 { | |
500 struct ipa_ref *ref = NULL; | |
501 for (int i = 0; node->iterate_reference (i, ref); i++) | |
502 enqueue_node (ref->referred, &first, &reachable); | |
503 } | |
504 } | |
505 | |
506 /* Remove unreachable functions. */ | |
507 for (node = first_function (); node; node = next) | |
508 { | |
509 next = next_function (node); | |
510 | |
511 /* If node is not needed at all, remove it. */ | |
512 if (!node->aux) | |
513 { | |
514 if (file) | |
515 fprintf (file, " %s", node->dump_name ()); | |
516 node->remove (); | |
517 changed = true; | |
518 } | |
519 /* If node is unreachable, remove its body. */ | |
520 else if (!reachable.contains (node)) | |
521 { | |
522 /* We keep definitions of thunks and aliases in the boundary so | |
523 we can walk to the ultimate alias targets and function symbols | |
524 reliably. */ | |
525 if (node->alias || node->thunk.thunk_p) | |
526 ; | |
145 | 527 else if (!body_needed_for_clonning.contains (node->decl)) |
528 { | |
529 /* Make the node a non-clone so that we do not attempt to | |
530 materialize it later. */ | |
531 if (node->clone_of) | |
532 node->remove_from_clone_tree (); | |
533 node->release_body (); | |
534 } | |
111 | 535 else if (!node->clone_of) |
536 gcc_assert (in_lto_p || DECL_RESULT (node->decl)); | |
537 if (node->definition && !node->alias && !node->thunk.thunk_p) | |
538 { | |
539 if (file) | |
540 fprintf (file, " %s", node->dump_name ()); | |
541 node->body_removed = true; | |
542 node->analyzed = false; | |
543 node->definition = false; | |
544 node->cpp_implicit_alias = false; | |
545 node->alias = false; | |
546 node->transparent_alias = false; | |
547 node->thunk.thunk_p = false; | |
548 node->weakref = false; | |
549 /* After early inlining we drop always_inline attributes on | |
550 bodies of functions that are still referenced (have their | |
551 address taken). */ | |
552 DECL_ATTRIBUTES (node->decl) | |
553 = remove_attribute ("always_inline", | |
554 DECL_ATTRIBUTES (node->decl)); | |
555 if (!node->in_other_partition) | |
145 | 556 node->local = false; |
111 | 557 node->remove_callees (); |
558 node->remove_all_references (); | |
559 changed = true; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
560 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
561 } |
111 | 562 else |
563 gcc_assert (node->clone_of || !node->has_gimple_body_p () | |
564 || in_lto_p || DECL_RESULT (node->decl)); | |
0 | 565 } |
566 | |
111 | 567 /* Inline clones might be kept around so their materializing allows further |
568 cloning. If the function the clone is inlined into is removed, we need | |
569 to turn it into normal cone. */ | |
570 FOR_EACH_FUNCTION (node) | |
0 | 571 { |
145 | 572 if (node->inlined_to |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
573 && !node->callers) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
574 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
575 gcc_assert (node->clones); |
145 | 576 node->inlined_to = NULL; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
577 update_inlined_to_pointer (node, node); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
578 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
579 node->aux = NULL; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
580 } |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
581 |
111 | 582 /* Remove unreachable variables. */ |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
583 if (file) |
111 | 584 fprintf (file, "\nReclaiming variables:"); |
585 for (vnode = first_variable (); vnode; vnode = vnext) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
586 { |
111 | 587 vnext = next_variable (vnode); |
588 if (!vnode->aux | |
589 /* For can_refer_decl_in_current_unit_p we want to track for | |
590 all external variables if they are defined in other partition | |
591 or not. */ | |
592 && (!flag_ltrans || !DECL_EXTERNAL (vnode->decl))) | |
593 { | |
594 struct ipa_ref *ref = NULL; | |
595 | |
596 /* First remove the aliases, so varpool::remove can possibly lookup | |
597 the constructor and save it for future use. */ | |
598 while (vnode->iterate_direct_aliases (0, ref)) | |
599 { | |
600 if (file) | |
601 fprintf (file, " %s", ref->referred->dump_name ()); | |
602 ref->referring->remove (); | |
603 } | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
604 if (file) |
111 | 605 fprintf (file, " %s", vnode->dump_name ()); |
606 vnext = next_variable (vnode); | |
607 /* Signal removal to the debug machinery. */ | |
131 | 608 if (! flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO) |
111 | 609 { |
610 vnode->definition = false; | |
611 (*debug_hooks->late_global_decl) (vnode->decl); | |
612 } | |
613 vnode->remove (); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
614 changed = true; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
615 } |
111 | 616 else if (!reachable.contains (vnode) && !vnode->alias) |
617 { | |
618 tree init; | |
619 if (vnode->definition) | |
620 { | |
621 if (file) | |
145 | 622 fprintf (file, " %s", vnode->dump_name ()); |
111 | 623 changed = true; |
624 } | |
625 /* Keep body if it may be useful for constant folding. */ | |
131 | 626 if ((flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO) |
627 || ((init = ctor_for_folding (vnode->decl)) == error_mark_node)) | |
111 | 628 vnode->remove_initializer (); |
629 else | |
630 DECL_INITIAL (vnode->decl) = init; | |
631 vnode->body_removed = true; | |
632 vnode->definition = false; | |
633 vnode->analyzed = false; | |
634 vnode->aux = NULL; | |
635 | |
636 vnode->remove_from_same_comdat_group (); | |
637 | |
638 vnode->remove_all_references (); | |
639 } | |
640 else | |
641 vnode->aux = NULL; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
642 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
643 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
644 /* Now update address_taken flags and try to promote functions to be local. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
645 if (file) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
646 fprintf (file, "\nClearing address taken flags:"); |
111 | 647 FOR_EACH_DEFINED_FUNCTION (node) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
648 if (node->address_taken |
111 | 649 && !node->used_from_other_partition) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
650 { |
111 | 651 if (!node->call_for_symbol_and_aliases |
131 | 652 (has_addr_references_p, NULL, true)) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
653 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
654 if (file) |
145 | 655 fprintf (file, " %s", node->dump_name ()); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
656 node->address_taken = false; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
657 changed = true; |
111 | 658 if (node->local_p () |
659 /* Virtual functions may be kept in cgraph just because | |
660 of possible later devirtualization. Do not mark them as | |
661 local too early so we won't optimize them out before | |
662 we are done with polymorphic call analysis. */ | |
145 | 663 && (symtab->state >= IPA_SSA_AFTER_INLINING |
111 | 664 || !node->call_for_symbol_and_aliases |
665 (is_indirect_call_target_p, NULL, true))) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
666 { |
145 | 667 node->local = true; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
668 if (file) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
669 fprintf (file, " (local)"); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
670 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
671 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
672 } |
111 | 673 if (file) |
674 fprintf (file, "\n"); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
675 |
111 | 676 symtab_node::checking_verify_symtab_nodes (); |
677 | |
678 /* If we removed something, perhaps profile could be improved. */ | |
679 if (changed && (optimize || in_lto_p) && ipa_call_summaries) | |
680 FOR_EACH_DEFINED_FUNCTION (node) | |
681 ipa_propagate_frequency (node); | |
682 | |
683 timevar_pop (TV_IPA_UNREACHABLE); | |
684 return changed; | |
685 } | |
686 | |
687 /* Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ | |
688 as needed, also clear EXPLICIT_REFS if the references to given variable | |
689 do not need to be explicit. */ | |
690 | |
691 void | |
692 process_references (varpool_node *vnode, | |
693 bool *written, bool *address_taken, | |
694 bool *read, bool *explicit_refs) | |
695 { | |
696 int i; | |
697 struct ipa_ref *ref; | |
698 | |
699 if (!vnode->all_refs_explicit_p () | |
700 || TREE_THIS_VOLATILE (vnode->decl)) | |
701 *explicit_refs = false; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
702 |
111 | 703 for (i = 0; vnode->iterate_referring (i, ref) |
704 && *explicit_refs && (!*written || !*address_taken || !*read); i++) | |
705 switch (ref->use) | |
706 { | |
707 case IPA_REF_ADDR: | |
708 *address_taken = true; | |
709 break; | |
710 case IPA_REF_LOAD: | |
711 *read = true; | |
712 break; | |
713 case IPA_REF_STORE: | |
714 *written = true; | |
715 break; | |
716 case IPA_REF_ALIAS: | |
717 process_references (dyn_cast<varpool_node *> (ref->referring), written, | |
718 address_taken, read, explicit_refs); | |
719 break; | |
720 } | |
721 } | |
722 | |
723 /* Set TREE_READONLY bit. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
724 |
111 | 725 bool |
726 set_readonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED) | |
727 { | |
728 TREE_READONLY (vnode->decl) = true; | |
729 return false; | |
730 } | |
731 | |
732 /* Set writeonly bit and clear the initalizer, since it will not be needed. */ | |
733 | |
734 bool | |
735 set_writeonly_bit (varpool_node *vnode, void *data) | |
736 { | |
737 vnode->writeonly = true; | |
738 if (optimize || in_lto_p) | |
739 { | |
740 DECL_INITIAL (vnode->decl) = NULL; | |
741 if (!vnode->alias) | |
742 { | |
743 if (vnode->num_references ()) | |
744 *(bool *)data = true; | |
745 vnode->remove_all_references (); | |
746 } | |
747 } | |
748 return false; | |
749 } | |
750 | |
751 /* Clear addressale bit of VNODE. */ | |
752 | |
753 bool | |
754 clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED) | |
755 { | |
756 vnode->address_taken = false; | |
757 TREE_ADDRESSABLE (vnode->decl) = 0; | |
758 return false; | |
0 | 759 } |
760 | |
145 | 761 /* Discover variables that have no longer address taken, are read-only or |
762 write-only and update their flags. | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
763 |
145 | 764 Return true when unreachable symbol removal should be done. |
111 | 765 |
145 | 766 FIXME: This cannot be done in between gimplify and omp_expand since |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
767 readonly flag plays role on what is shared and what is not. Currently we do |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
768 this transformation as part of whole program visibility and re-do at |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
769 ipa-reference pass (to take into account clonning), but it would |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
770 make sense to do it before early optimizations. */ |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
771 |
111 | 772 bool |
145 | 773 ipa_discover_variable_flags (void) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
774 { |
145 | 775 if (!flag_ipa_reference_addressable) |
776 return false; | |
777 | |
111 | 778 bool remove_p = false; |
779 varpool_node *vnode; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
780 if (dump_file) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
781 fprintf (dump_file, "Clearing variable flags:"); |
111 | 782 FOR_EACH_VARIABLE (vnode) |
783 if (!vnode->alias | |
784 && (TREE_ADDRESSABLE (vnode->decl) | |
785 || !vnode->writeonly | |
786 || !TREE_READONLY (vnode->decl))) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
787 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
788 bool written = false; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
789 bool address_taken = false; |
111 | 790 bool read = false; |
791 bool explicit_refs = true; | |
792 | |
793 process_references (vnode, &written, &address_taken, &read, | |
794 &explicit_refs); | |
795 if (!explicit_refs) | |
796 continue; | |
797 if (!address_taken) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
798 { |
111 | 799 if (TREE_ADDRESSABLE (vnode->decl) && dump_file) |
145 | 800 fprintf (dump_file, " %s (non-addressable)", |
801 vnode->dump_name ()); | |
111 | 802 vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL, |
803 true); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
804 } |
111 | 805 if (!address_taken && !written |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
806 /* Making variable in explicit section readonly can cause section |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
807 type conflict. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
808 See e.g. gcc.c-torture/compile/pr23237.c */ |
111 | 809 && vnode->get_section () == NULL) |
810 { | |
811 if (!TREE_READONLY (vnode->decl) && dump_file) | |
145 | 812 fprintf (dump_file, " %s (read-only)", vnode->dump_name ()); |
111 | 813 vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true); |
814 } | |
815 if (!vnode->writeonly && !read && !address_taken && written) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
816 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
817 if (dump_file) |
145 | 818 fprintf (dump_file, " %s (write-only)", vnode->dump_name ()); |
111 | 819 vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p, |
820 true); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
821 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
822 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
823 if (dump_file) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
824 fprintf (dump_file, "\n"); |
111 | 825 return remove_p; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
826 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
827 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
828 /* Generate and emit a static constructor or destructor. WHICH must |
131 | 829 be one of 'I' (for a constructor), 'D' (for a destructor). |
830 BODY is a STATEMENT_LIST containing GENERIC | |
111 | 831 statements. PRIORITY is the initialization priority for this |
832 constructor or destructor. | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
833 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
834 FINAL specify whether the externally visible name for collect2 should |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
835 be produced. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
836 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
837 static void |
145 | 838 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final, |
839 tree optimization, | |
840 tree target) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
841 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
842 static int counter = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
843 char which_buf[16]; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
844 tree decl, name, resdecl; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
845 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
846 /* The priority is encoded in the constructor or destructor name. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
847 collect2 will sort the names and arrange that they are called at |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
848 program startup. */ |
145 | 849 if (!targetm.have_ctors_dtors && final) |
850 { | |
851 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++); | |
852 name = get_file_function_name (which_buf); | |
853 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
854 else |
145 | 855 { |
856 /* Proudce sane name but one not recognizable by collect2, just for the | |
857 case we fail to inline the function. */ | |
858 sprintf (which_buf, "_sub_%c_%.5d_%d", which, priority, counter++); | |
859 name = get_identifier (which_buf); | |
860 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
861 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
862 decl = build_decl (input_location, FUNCTION_DECL, name, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
863 build_function_type_list (void_type_node, NULL_TREE)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
864 current_function_decl = decl; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
865 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
866 resdecl = build_decl (input_location, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
867 RESULT_DECL, NULL_TREE, void_type_node); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
868 DECL_ARTIFICIAL (resdecl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
869 DECL_RESULT (decl) = resdecl; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
870 DECL_CONTEXT (resdecl) = decl; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
871 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
872 allocate_struct_function (decl, false); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
873 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
874 TREE_STATIC (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
875 TREE_USED (decl) = 1; |
145 | 876 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) = optimization; |
877 DECL_FUNCTION_SPECIFIC_TARGET (decl) = target; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
878 DECL_ARTIFICIAL (decl) = 1; |
111 | 879 DECL_IGNORED_P (decl) = 1; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
880 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
881 DECL_SAVED_TREE (decl) = body; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
882 if (!targetm.have_ctors_dtors && final) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
883 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
884 TREE_PUBLIC (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
885 DECL_PRESERVE_P (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
886 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
887 DECL_UNINLINABLE (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
888 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
889 DECL_INITIAL (decl) = make_node (BLOCK); |
111 | 890 BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
891 TREE_USED (DECL_INITIAL (decl)) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
892 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
893 DECL_SOURCE_LOCATION (decl) = input_location; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
894 cfun->function_end_locus = input_location; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
895 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
896 switch (which) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
897 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
898 case 'I': |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
899 DECL_STATIC_CONSTRUCTOR (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
900 decl_init_priority_insert (decl, priority); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
901 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
902 case 'D': |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
903 DECL_STATIC_DESTRUCTOR (decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
904 decl_fini_priority_insert (decl, priority); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
905 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
906 default: |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
907 gcc_unreachable (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
908 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
909 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
910 gimplify_function_tree (decl); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
911 |
111 | 912 cgraph_node::add_new_function (decl, false); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
913 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
914 set_cfun (NULL); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
915 current_function_decl = NULL; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
916 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
917 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
918 /* Generate and emit a static constructor or destructor. WHICH must |
131 | 919 be one of 'I' (for a constructor) or 'D' (for a destructor). |
920 BODY is a STATEMENT_LIST containing GENERIC | |
111 | 921 statements. PRIORITY is the initialization priority for this |
922 constructor or destructor. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
923 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
924 void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
925 cgraph_build_static_cdtor (char which, tree body, int priority) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
926 { |
145 | 927 /* FIXME: We should be able to |
928 gcc_assert (!in_lto_p); | |
929 because at LTO time the global options are not safe to use. | |
930 Unfortunately ASAN finish_file will produce constructors late and they | |
931 may lead to surprises. */ | |
932 cgraph_build_static_cdtor_1 (which, body, priority, false, | |
933 optimization_default_node, | |
934 target_option_default_node); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
935 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
936 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
937 /* When target does not have ctors and dtors, we call all constructor |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
938 and destructor by special initialization/destruction function |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
939 recognized by collect2. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
940 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
941 When we are going to build this function, collect all constructors and |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
942 destructors and turn them into normal functions. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
943 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
944 static void |
111 | 945 record_cdtor_fn (struct cgraph_node *node, vec<tree> *ctors, vec<tree> *dtors) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
946 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
947 if (DECL_STATIC_CONSTRUCTOR (node->decl)) |
111 | 948 ctors->safe_push (node->decl); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
949 if (DECL_STATIC_DESTRUCTOR (node->decl)) |
111 | 950 dtors->safe_push (node->decl); |
951 node = cgraph_node::get (node->decl); | |
952 DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
953 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
954 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
955 /* Define global constructors/destructor functions for the CDTORS, of |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
956 which they are LEN. The CDTORS are sorted by initialization |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
957 priority. If CTOR_P is true, these are constructors; otherwise, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
958 they are destructors. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
959 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
960 static void |
111 | 961 build_cdtor (bool ctor_p, const vec<tree> &cdtors) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
962 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
963 size_t i,j; |
111 | 964 size_t len = cdtors.length (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
965 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
966 i = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
967 while (i < len) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
968 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
969 tree body; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
970 tree fn; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
971 priority_type priority; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
972 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
973 priority = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
974 body = NULL_TREE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
975 j = i; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
976 do |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
977 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
978 priority_type p; |
111 | 979 fn = cdtors[j]; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
980 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
981 if (j == i) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
982 priority = p; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
983 else if (p != priority) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
984 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
985 j++; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
986 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
987 while (j < len); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
988 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
989 /* When there is only one cdtor and target supports them, do nothing. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
990 if (j == i + 1 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
991 && targetm.have_ctors_dtors) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
992 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
993 i++; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
994 continue; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
995 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
996 /* Find the next batch of constructors/destructors with the same |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
997 initialization priority. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
998 for (;i < j; i++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
999 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1000 tree call; |
111 | 1001 fn = cdtors[i]; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1002 call = build_call_expr (fn, 0); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1003 if (ctor_p) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1004 DECL_STATIC_CONSTRUCTOR (fn) = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1005 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1006 DECL_STATIC_DESTRUCTOR (fn) = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1007 /* We do not want to optimize away pure/const calls here. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1008 When optimizing, these should be already removed, when not |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1009 optimizing, we want user to be able to breakpoint in them. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1010 TREE_SIDE_EFFECTS (call) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1011 append_to_statement_list (call, &body); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1012 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1013 gcc_assert (body != NULL_TREE); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1014 /* Generate a function to call all the function of like |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1015 priority. */ |
145 | 1016 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true, |
1017 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (cdtors[0]), | |
1018 DECL_FUNCTION_SPECIFIC_TARGET (cdtors[0])); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1019 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1020 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1021 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1022 /* Comparison function for qsort. P1 and P2 are actually of type |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1023 "tree *" and point to static constructors. DECL_INIT_PRIORITY is |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1024 used to determine the sort order. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1025 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1026 static int |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1027 compare_ctor (const void *p1, const void *p2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1028 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1029 tree f1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1030 tree f2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1031 int priority1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1032 int priority2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1033 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1034 f1 = *(const tree *)p1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1035 f2 = *(const tree *)p2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1036 priority1 = DECL_INIT_PRIORITY (f1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1037 priority2 = DECL_INIT_PRIORITY (f2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1038 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1039 if (priority1 < priority2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1040 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1041 else if (priority1 > priority2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1042 return 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1043 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1044 /* Ensure a stable sort. Constructors are executed in backwarding |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1045 order to make LTO initialize braries first. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1046 return DECL_UID (f2) - DECL_UID (f1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1047 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1048 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1049 /* Comparison function for qsort. P1 and P2 are actually of type |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1050 "tree *" and point to static destructors. DECL_FINI_PRIORITY is |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1051 used to determine the sort order. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1052 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1053 static int |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1054 compare_dtor (const void *p1, const void *p2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1055 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1056 tree f1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1057 tree f2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1058 int priority1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1059 int priority2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1060 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1061 f1 = *(const tree *)p1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1062 f2 = *(const tree *)p2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1063 priority1 = DECL_FINI_PRIORITY (f1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1064 priority2 = DECL_FINI_PRIORITY (f2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1065 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1066 if (priority1 < priority2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1067 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1068 else if (priority1 > priority2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1069 return 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1070 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1071 /* Ensure a stable sort. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1072 return DECL_UID (f1) - DECL_UID (f2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1073 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1074 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1075 /* Generate functions to call static constructors and destructors |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1076 for targets that do not support .ctors/.dtors sections. These |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1077 functions have magic names which are detected by collect2. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1078 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1079 static void |
111 | 1080 build_cdtor_fns (vec<tree> *ctors, vec<tree> *dtors) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1081 { |
111 | 1082 if (!ctors->is_empty ()) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1083 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1084 gcc_assert (!targetm.have_ctors_dtors || in_lto_p); |
111 | 1085 ctors->qsort (compare_ctor); |
1086 build_cdtor (/*ctor_p=*/true, *ctors); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1087 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1088 |
111 | 1089 if (!dtors->is_empty ()) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1090 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1091 gcc_assert (!targetm.have_ctors_dtors || in_lto_p); |
111 | 1092 dtors->qsort (compare_dtor); |
1093 build_cdtor (/*ctor_p=*/false, *dtors); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1094 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1095 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1096 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1097 /* Look for constructors and destructors and produce function calling them. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1098 This is needed for targets not supporting ctors or dtors, but we perform the |
111 | 1099 transformation also at linktime to merge possibly numerous |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1100 constructors/destructors into single function to improve code locality and |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1101 reduce size. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1102 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1103 static unsigned int |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1104 ipa_cdtor_merge (void) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1105 { |
111 | 1106 /* A vector of FUNCTION_DECLs declared as static constructors. */ |
1107 auto_vec<tree, 20> ctors; | |
1108 /* A vector of FUNCTION_DECLs declared as static destructors. */ | |
1109 auto_vec<tree, 20> dtors; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1110 struct cgraph_node *node; |
111 | 1111 FOR_EACH_DEFINED_FUNCTION (node) |
1112 if (DECL_STATIC_CONSTRUCTOR (node->decl) | |
1113 || DECL_STATIC_DESTRUCTOR (node->decl)) | |
1114 record_cdtor_fn (node, &ctors, &dtors); | |
1115 build_cdtor_fns (&ctors, &dtors); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1116 return 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1117 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1118 |
111 | 1119 namespace { |
1120 | |
1121 const pass_data pass_data_ipa_cdtor_merge = | |
1122 { | |
1123 IPA_PASS, /* type */ | |
1124 "cdtor", /* name */ | |
1125 OPTGROUP_NONE, /* optinfo_flags */ | |
1126 TV_CGRAPHOPT, /* tv_id */ | |
1127 0, /* properties_required */ | |
1128 0, /* properties_provided */ | |
1129 0, /* properties_destroyed */ | |
1130 0, /* todo_flags_start */ | |
1131 0, /* todo_flags_finish */ | |
1132 }; | |
1133 | |
1134 class pass_ipa_cdtor_merge : public ipa_opt_pass_d | |
1135 { | |
1136 public: | |
1137 pass_ipa_cdtor_merge (gcc::context *ctxt) | |
1138 : ipa_opt_pass_d (pass_data_ipa_cdtor_merge, ctxt, | |
1139 NULL, /* generate_summary */ | |
1140 NULL, /* write_summary */ | |
1141 NULL, /* read_summary */ | |
1142 NULL, /* write_optimization_summary */ | |
1143 NULL, /* read_optimization_summary */ | |
1144 NULL, /* stmt_fixup */ | |
1145 0, /* function_transform_todo_flags_start */ | |
1146 NULL, /* function_transform */ | |
1147 NULL) /* variable_transform */ | |
1148 {} | |
1149 | |
1150 /* opt_pass methods: */ | |
1151 virtual bool gate (function *); | |
1152 virtual unsigned int execute (function *) { return ipa_cdtor_merge (); } | |
1153 | |
1154 }; // class pass_ipa_cdtor_merge | |
1155 | |
1156 bool | |
1157 pass_ipa_cdtor_merge::gate (function *) | |
1158 { | |
1159 /* Perform the pass when we have no ctors/dtors support | |
1160 or at LTO time to merge multiple constructors into single | |
1161 function. */ | |
1162 return !targetm.have_ctors_dtors || in_lto_p; | |
1163 } | |
1164 | |
1165 } // anon namespace | |
1166 | |
1167 ipa_opt_pass_d * | |
1168 make_pass_ipa_cdtor_merge (gcc::context *ctxt) | |
1169 { | |
1170 return new pass_ipa_cdtor_merge (ctxt); | |
1171 } | |
1172 | |
1173 /* Invalid pointer representing BOTTOM for single user dataflow. */ | |
1174 #define BOTTOM ((cgraph_node *)(size_t) 2) | |
1175 | |
1176 /* Meet operation for single user dataflow. | |
1177 Here we want to associate variables with sigle function that may access it. | |
1178 | |
1179 FUNCTION is current single user of a variable, VAR is variable that uses it. | |
1180 Latttice is stored in SINGLE_USER_MAP. | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1181 |
111 | 1182 We represent: |
1183 - TOP by no entry in SIGNLE_USER_MAP | |
1184 - BOTTOM by BOTTOM in AUX pointer (to save lookups) | |
1185 - known single user by cgraph pointer in SINGLE_USER_MAP. */ | |
1186 | |
1187 cgraph_node * | |
1188 meet (cgraph_node *function, varpool_node *var, | |
1189 hash_map<varpool_node *, cgraph_node *> &single_user_map) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1190 { |
111 | 1191 struct cgraph_node *user, **f; |
1192 | |
1193 if (var->aux == BOTTOM) | |
1194 return BOTTOM; | |
1195 | |
1196 f = single_user_map.get (var); | |
1197 if (!f) | |
1198 return function; | |
1199 user = *f; | |
1200 if (!function) | |
1201 return user; | |
1202 else if (function != user) | |
1203 return BOTTOM; | |
1204 else | |
1205 return function; | |
1206 } | |
1207 | |
1208 /* Propagation step of single-use dataflow. | |
1209 | |
1210 Check all uses of VNODE and see if they are used by single function FUNCTION. | |
1211 SINGLE_USER_MAP represents the dataflow lattice. */ | |
1212 | |
1213 cgraph_node * | |
1214 propagate_single_user (varpool_node *vnode, cgraph_node *function, | |
1215 hash_map<varpool_node *, cgraph_node *> &single_user_map) | |
1216 { | |
1217 int i; | |
1218 struct ipa_ref *ref; | |
1219 | |
1220 gcc_assert (!vnode->externally_visible); | |
1221 | |
1222 /* If node is an alias, first meet with its target. */ | |
1223 if (vnode->alias) | |
1224 function = meet (function, vnode->get_alias_target (), single_user_map); | |
1225 | |
1226 /* Check all users and see if they correspond to a single function. */ | |
1227 for (i = 0; vnode->iterate_referring (i, ref) && function != BOTTOM; i++) | |
1228 { | |
1229 struct cgraph_node *cnode = dyn_cast <cgraph_node *> (ref->referring); | |
1230 if (cnode) | |
1231 { | |
145 | 1232 if (cnode->inlined_to) |
1233 cnode = cnode->inlined_to; | |
111 | 1234 if (!function) |
1235 function = cnode; | |
1236 else if (function != cnode) | |
1237 function = BOTTOM; | |
1238 } | |
1239 else | |
1240 function = meet (function, dyn_cast <varpool_node *> (ref->referring), | |
1241 single_user_map); | |
1242 } | |
1243 return function; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1244 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1245 |
111 | 1246 /* Pass setting used_by_single_function flag. |
1247 This flag is set on variable when there is only one function that may | |
1248 possibly referr to it. */ | |
1249 | |
1250 static unsigned int | |
1251 ipa_single_use (void) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1252 { |
111 | 1253 varpool_node *first = (varpool_node *) (void *) 1; |
1254 varpool_node *var; | |
1255 hash_map<varpool_node *, cgraph_node *> single_user_map; | |
1256 | |
1257 FOR_EACH_DEFINED_VARIABLE (var) | |
1258 if (!var->all_refs_explicit_p ()) | |
1259 var->aux = BOTTOM; | |
1260 else | |
1261 { | |
1262 /* Enqueue symbol for dataflow. */ | |
1263 var->aux = first; | |
1264 first = var; | |
1265 } | |
1266 | |
1267 /* The actual dataflow. */ | |
1268 | |
1269 while (first != (void *) 1) | |
1270 { | |
1271 cgraph_node *user, *orig_user, **f; | |
1272 | |
1273 var = first; | |
1274 first = (varpool_node *)first->aux; | |
1275 | |
1276 f = single_user_map.get (var); | |
1277 if (f) | |
1278 orig_user = *f; | |
1279 else | |
1280 orig_user = NULL; | |
1281 user = propagate_single_user (var, orig_user, single_user_map); | |
1282 | |
1283 gcc_checking_assert (var->aux != BOTTOM); | |
1284 | |
1285 /* If user differs, enqueue all references. */ | |
1286 if (user != orig_user) | |
1287 { | |
1288 unsigned int i; | |
1289 ipa_ref *ref; | |
1290 | |
1291 single_user_map.put (var, user); | |
1292 | |
1293 /* Enqueue all aliases for re-processing. */ | |
1294 for (i = 0; var->iterate_direct_aliases (i, ref); i++) | |
1295 if (!ref->referring->aux) | |
1296 { | |
1297 ref->referring->aux = first; | |
1298 first = dyn_cast <varpool_node *> (ref->referring); | |
1299 } | |
1300 /* Enqueue all users for re-processing. */ | |
1301 for (i = 0; var->iterate_reference (i, ref); i++) | |
1302 if (!ref->referred->aux | |
1303 && ref->referred->definition | |
1304 && is_a <varpool_node *> (ref->referred)) | |
1305 { | |
1306 ref->referred->aux = first; | |
1307 first = dyn_cast <varpool_node *> (ref->referred); | |
1308 } | |
1309 | |
1310 /* If user is BOTTOM, just punt on this var. */ | |
1311 if (user == BOTTOM) | |
1312 var->aux = BOTTOM; | |
1313 else | |
1314 var->aux = NULL; | |
1315 } | |
1316 else | |
1317 var->aux = NULL; | |
1318 } | |
1319 | |
1320 FOR_EACH_DEFINED_VARIABLE (var) | |
1321 { | |
1322 if (var->aux != BOTTOM) | |
1323 { | |
1324 /* Not having the single user known means that the VAR is | |
1325 unreachable. Either someone forgot to remove unreachable | |
1326 variables or the reachability here is wrong. */ | |
1327 | |
1328 gcc_checking_assert (single_user_map.get (var)); | |
1329 | |
1330 if (dump_file) | |
1331 { | |
1332 fprintf (dump_file, "Variable %s is used by single function\n", | |
1333 var->dump_name ()); | |
1334 } | |
1335 var->used_by_single_function = true; | |
1336 } | |
1337 var->aux = NULL; | |
1338 } | |
1339 return 0; | |
1340 } | |
1341 | |
1342 namespace { | |
1343 | |
1344 const pass_data pass_data_ipa_single_use = | |
1345 { | |
1346 IPA_PASS, /* type */ | |
1347 "single-use", /* name */ | |
1348 OPTGROUP_NONE, /* optinfo_flags */ | |
1349 TV_CGRAPHOPT, /* tv_id */ | |
1350 0, /* properties_required */ | |
1351 0, /* properties_provided */ | |
1352 0, /* properties_destroyed */ | |
1353 0, /* todo_flags_start */ | |
1354 0, /* todo_flags_finish */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1355 }; |
111 | 1356 |
1357 class pass_ipa_single_use : public ipa_opt_pass_d | |
1358 { | |
1359 public: | |
1360 pass_ipa_single_use (gcc::context *ctxt) | |
1361 : ipa_opt_pass_d (pass_data_ipa_single_use, ctxt, | |
1362 NULL, /* generate_summary */ | |
1363 NULL, /* write_summary */ | |
1364 NULL, /* read_summary */ | |
1365 NULL, /* write_optimization_summary */ | |
1366 NULL, /* read_optimization_summary */ | |
1367 NULL, /* stmt_fixup */ | |
1368 0, /* function_transform_todo_flags_start */ | |
1369 NULL, /* function_transform */ | |
1370 NULL) /* variable_transform */ | |
1371 {} | |
1372 | |
1373 /* opt_pass methods: */ | |
1374 virtual unsigned int execute (function *) { return ipa_single_use (); } | |
1375 | |
1376 }; // class pass_ipa_single_use | |
1377 | |
1378 } // anon namespace | |
1379 | |
1380 ipa_opt_pass_d * | |
1381 make_pass_ipa_single_use (gcc::context *ctxt) | |
1382 { | |
1383 return new pass_ipa_single_use (ctxt); | |
1384 } | |
1385 | |
1386 /* Materialize all clones. */ | |
1387 | |
1388 namespace { | |
1389 | |
1390 const pass_data pass_data_materialize_all_clones = | |
1391 { | |
1392 SIMPLE_IPA_PASS, /* type */ | |
1393 "materialize-all-clones", /* name */ | |
1394 OPTGROUP_NONE, /* optinfo_flags */ | |
1395 TV_IPA_OPT, /* tv_id */ | |
1396 0, /* properties_required */ | |
1397 0, /* properties_provided */ | |
1398 0, /* properties_destroyed */ | |
1399 0, /* todo_flags_start */ | |
1400 0, /* todo_flags_finish */ | |
1401 }; | |
1402 | |
1403 class pass_materialize_all_clones : public simple_ipa_opt_pass | |
1404 { | |
1405 public: | |
1406 pass_materialize_all_clones (gcc::context *ctxt) | |
1407 : simple_ipa_opt_pass (pass_data_materialize_all_clones, ctxt) | |
1408 {} | |
1409 | |
1410 /* opt_pass methods: */ | |
1411 virtual unsigned int execute (function *) | |
1412 { | |
1413 symtab->materialize_all_clones (); | |
1414 return 0; | |
1415 } | |
1416 | |
1417 }; // class pass_materialize_all_clones | |
1418 | |
1419 } // anon namespace | |
1420 | |
1421 simple_ipa_opt_pass * | |
1422 make_pass_materialize_all_clones (gcc::context *ctxt) | |
1423 { | |
1424 return new pass_materialize_all_clones (ctxt); | |
1425 } |