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