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