Mercurial > hg > CbC > CbC_gcc
annotate gcc/ipa-utils.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | 77e2b8dfacca |
children | 84e7813d76e9 |
rev | line source |
---|---|
0 | 1 /* Utilities for ipa analysis. |
111 | 2 Copyright (C) 2005-2017 Free Software Foundation, Inc. |
0 | 3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it under | |
8 the terms of the GNU General Public License as published by the Free | |
9 Software Foundation; either version 3, or (at your option) any later | |
10 version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 #include "config.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
111 | 24 #include "backend.h" |
0 | 25 #include "tree.h" |
111 | 26 #include "gimple.h" |
27 #include "predict.h" | |
28 #include "alloc-pool.h" | |
29 #include "cgraph.h" | |
30 #include "lto-streamer.h" | |
31 #include "dumpfile.h" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
32 #include "splay-tree.h" |
0 | 33 #include "ipa-utils.h" |
111 | 34 #include "symbol-summary.h" |
35 #include "tree-vrp.h" | |
36 #include "ipa-prop.h" | |
37 #include "ipa-fnsummary.h" | |
0 | 38 |
39 /* Debugging function for postorder and inorder code. NOTE is a string | |
40 that is printed before the nodes are printed. ORDER is an array of | |
41 cgraph_nodes that has COUNT useful nodes in it. */ | |
42 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
43 void |
111 | 44 ipa_print_order (FILE* out, |
45 const char * note, | |
46 struct cgraph_node** order, | |
47 int count) | |
0 | 48 { |
49 int i; | |
50 fprintf (out, "\n\n ordered call graph: %s\n", note); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
51 |
0 | 52 for (i = count - 1; i >= 0; i--) |
111 | 53 order[i]->dump (out); |
0 | 54 fprintf (out, "\n"); |
111 | 55 fflush (out); |
0 | 56 } |
57 | |
111 | 58 |
0 | 59 struct searchc_env { |
60 struct cgraph_node **stack; | |
111 | 61 struct cgraph_node **result; |
0 | 62 int stack_size; |
63 int order_pos; | |
64 splay_tree nodes_marked_new; | |
65 bool reduce; | |
111 | 66 bool allow_overwritable; |
0 | 67 int count; |
68 }; | |
69 | |
70 /* This is an implementation of Tarjan's strongly connected region | |
71 finder as reprinted in Aho Hopcraft and Ullman's The Design and | |
72 Analysis of Computer Programs (1975) pages 192-193. This version | |
73 has been customized for cgraph_nodes. The env parameter is because | |
74 it is recursive and there are no nested functions here. This | |
75 function should only be called from itself or | |
111 | 76 ipa_reduced_postorder. ENV is a stack env and would be |
0 | 77 unnecessary if C had nested functions. V is the node to start |
78 searching from. */ | |
79 | |
80 static void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
81 searchc (struct searchc_env* env, struct cgraph_node *v, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
82 bool (*ignore_edge) (struct cgraph_edge *)) |
0 | 83 { |
84 struct cgraph_edge *edge; | |
85 struct ipa_dfs_info *v_info = (struct ipa_dfs_info *) v->aux; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
86 |
0 | 87 /* mark node as old */ |
88 v_info->new_node = false; | |
89 splay_tree_remove (env->nodes_marked_new, v->uid); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
90 |
0 | 91 v_info->dfn_number = env->count; |
92 v_info->low_link = env->count; | |
93 env->count++; | |
94 env->stack[(env->stack_size)++] = v; | |
95 v_info->on_stack = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
96 |
0 | 97 for (edge = v->callees; edge; edge = edge->next_callee) |
98 { | |
99 struct ipa_dfs_info * w_info; | |
111 | 100 enum availability avail; |
101 struct cgraph_node *w = edge->callee->ultimate_alias_target (&avail); | |
0 | 102 |
111 | 103 if (!w || (ignore_edge && ignore_edge (edge))) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
104 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
105 |
111 | 106 if (w->aux |
107 && (avail > AVAIL_INTERPOSABLE | |
108 || (env->allow_overwritable && avail == AVAIL_INTERPOSABLE))) | |
0 | 109 { |
110 w_info = (struct ipa_dfs_info *) w->aux; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
111 if (w_info->new_node) |
0 | 112 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
113 searchc (env, w, ignore_edge); |
0 | 114 v_info->low_link = |
115 (v_info->low_link < w_info->low_link) ? | |
116 v_info->low_link : w_info->low_link; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
117 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
118 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
119 if ((w_info->dfn_number < v_info->dfn_number) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
120 && (w_info->on_stack)) |
0 | 121 v_info->low_link = |
122 (w_info->dfn_number < v_info->low_link) ? | |
123 w_info->dfn_number : v_info->low_link; | |
124 } | |
125 } | |
126 | |
127 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
128 if (v_info->low_link == v_info->dfn_number) |
0 | 129 { |
130 struct cgraph_node *last = NULL; | |
131 struct cgraph_node *x; | |
132 struct ipa_dfs_info *x_info; | |
133 do { | |
134 x = env->stack[--(env->stack_size)]; | |
135 x_info = (struct ipa_dfs_info *) x->aux; | |
136 x_info->on_stack = false; | |
111 | 137 x_info->scc_no = v_info->dfn_number; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
138 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
139 if (env->reduce) |
0 | 140 { |
141 x_info->next_cycle = last; | |
142 last = x; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
143 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
144 else |
0 | 145 env->result[env->order_pos++] = x; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
146 } |
0 | 147 while (v != x); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
148 if (env->reduce) |
0 | 149 env->result[env->order_pos++] = v; |
150 } | |
151 } | |
152 | |
153 /* Topsort the call graph by caller relation. Put the result in ORDER. | |
154 | |
111 | 155 The REDUCE flag is true if you want the cycles reduced to single nodes. |
156 You can use ipa_get_nodes_in_cycle to obtain a vector containing all real | |
157 call graph nodes in a reduced node. | |
158 | |
159 Set ALLOW_OVERWRITABLE if nodes with such availability should be included. | |
160 IGNORE_EDGE, if non-NULL is a hook that may make some edges insignificant | |
161 for the topological sort. */ | |
0 | 162 |
163 int | |
111 | 164 ipa_reduced_postorder (struct cgraph_node **order, |
165 bool reduce, bool allow_overwritable, | |
166 bool (*ignore_edge) (struct cgraph_edge *)) | |
0 | 167 { |
168 struct cgraph_node *node; | |
169 struct searchc_env env; | |
170 splay_tree_node result; | |
111 | 171 env.stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); |
0 | 172 env.stack_size = 0; |
173 env.result = order; | |
174 env.order_pos = 0; | |
175 env.nodes_marked_new = splay_tree_new (splay_tree_compare_ints, 0, 0); | |
176 env.count = 1; | |
177 env.reduce = reduce; | |
111 | 178 env.allow_overwritable = allow_overwritable; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
179 |
111 | 180 FOR_EACH_DEFINED_FUNCTION (node) |
0 | 181 { |
111 | 182 enum availability avail = node->get_availability (); |
0 | 183 |
111 | 184 if (avail > AVAIL_INTERPOSABLE |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
185 || (allow_overwritable |
111 | 186 && (avail == AVAIL_INTERPOSABLE))) |
0 | 187 { |
188 /* Reuse the info if it is already there. */ | |
189 struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->aux; | |
190 if (!info) | |
191 info = XCNEW (struct ipa_dfs_info); | |
192 info->new_node = true; | |
193 info->on_stack = false; | |
194 info->next_cycle = NULL; | |
195 node->aux = info; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
196 |
0 | 197 splay_tree_insert (env.nodes_marked_new, |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
198 (splay_tree_key)node->uid, |
0 | 199 (splay_tree_value)node); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
200 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
201 else |
0 | 202 node->aux = NULL; |
203 } | |
204 result = splay_tree_min (env.nodes_marked_new); | |
205 while (result) | |
206 { | |
207 node = (struct cgraph_node *)result->value; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
208 searchc (&env, node, ignore_edge); |
0 | 209 result = splay_tree_min (env.nodes_marked_new); |
210 } | |
211 splay_tree_delete (env.nodes_marked_new); | |
212 free (env.stack); | |
213 | |
214 return env.order_pos; | |
215 } | |
216 | |
111 | 217 /* Deallocate all ipa_dfs_info structures pointed to by the aux pointer of call |
218 graph nodes. */ | |
219 | |
220 void | |
221 ipa_free_postorder_info (void) | |
222 { | |
223 struct cgraph_node *node; | |
224 FOR_EACH_DEFINED_FUNCTION (node) | |
225 { | |
226 /* Get rid of the aux information. */ | |
227 if (node->aux) | |
228 { | |
229 free (node->aux); | |
230 node->aux = NULL; | |
231 } | |
232 } | |
233 } | |
234 | |
235 /* Get the set of nodes for the cycle in the reduced call graph starting | |
236 from NODE. */ | |
237 | |
238 vec<cgraph_node *> | |
239 ipa_get_nodes_in_cycle (struct cgraph_node *node) | |
240 { | |
241 vec<cgraph_node *> v = vNULL; | |
242 struct ipa_dfs_info *node_dfs_info; | |
243 while (node) | |
244 { | |
245 v.safe_push (node); | |
246 node_dfs_info = (struct ipa_dfs_info *) node->aux; | |
247 node = node_dfs_info->next_cycle; | |
248 } | |
249 return v; | |
250 } | |
251 | |
252 /* Return true iff the CS is an edge within a strongly connected component as | |
253 computed by ipa_reduced_postorder. */ | |
254 | |
255 bool | |
256 ipa_edge_within_scc (struct cgraph_edge *cs) | |
257 { | |
258 struct ipa_dfs_info *caller_dfs = (struct ipa_dfs_info *) cs->caller->aux; | |
259 struct ipa_dfs_info *callee_dfs; | |
260 struct cgraph_node *callee = cs->callee->function_symbol (); | |
261 | |
262 callee_dfs = (struct ipa_dfs_info *) callee->aux; | |
263 return (caller_dfs | |
264 && callee_dfs | |
265 && caller_dfs->scc_no == callee_dfs->scc_no); | |
266 } | |
267 | |
268 struct postorder_stack | |
269 { | |
270 struct cgraph_node *node; | |
271 struct cgraph_edge *edge; | |
272 int ref; | |
273 }; | |
274 | |
275 /* Fill array order with all nodes with output flag set in the reverse | |
276 topological order. Return the number of elements in the array. | |
277 FIXME: While walking, consider aliases, too. */ | |
278 | |
279 int | |
280 ipa_reverse_postorder (struct cgraph_node **order) | |
281 { | |
282 struct cgraph_node *node, *node2; | |
283 int stack_size = 0; | |
284 int order_pos = 0; | |
285 struct cgraph_edge *edge; | |
286 int pass; | |
287 struct ipa_ref *ref = NULL; | |
288 | |
289 struct postorder_stack *stack = | |
290 XCNEWVEC (struct postorder_stack, symtab->cgraph_count); | |
291 | |
292 /* We have to deal with cycles nicely, so use a depth first traversal | |
293 output algorithm. Ignore the fact that some functions won't need | |
294 to be output and put them into order as well, so we get dependencies | |
295 right through inline functions. */ | |
296 FOR_EACH_FUNCTION (node) | |
297 node->aux = NULL; | |
298 for (pass = 0; pass < 2; pass++) | |
299 FOR_EACH_FUNCTION (node) | |
300 if (!node->aux | |
301 && (pass | |
302 || (!node->address_taken | |
303 && !node->global.inlined_to | |
304 && !node->alias && !node->thunk.thunk_p | |
305 && !node->only_called_directly_p ()))) | |
306 { | |
307 stack_size = 0; | |
308 stack[stack_size].node = node; | |
309 stack[stack_size].edge = node->callers; | |
310 stack[stack_size].ref = 0; | |
311 node->aux = (void *)(size_t)1; | |
312 while (stack_size >= 0) | |
313 { | |
314 while (true) | |
315 { | |
316 node2 = NULL; | |
317 while (stack[stack_size].edge && !node2) | |
318 { | |
319 edge = stack[stack_size].edge; | |
320 node2 = edge->caller; | |
321 stack[stack_size].edge = edge->next_caller; | |
322 /* Break possible cycles involving always-inline | |
323 functions by ignoring edges from always-inline | |
324 functions to non-always-inline functions. */ | |
325 if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->decl) | |
326 && !DECL_DISREGARD_INLINE_LIMITS | |
327 (edge->callee->function_symbol ()->decl)) | |
328 node2 = NULL; | |
329 } | |
330 for (; stack[stack_size].node->iterate_referring ( | |
331 stack[stack_size].ref, | |
332 ref) && !node2; | |
333 stack[stack_size].ref++) | |
334 { | |
335 if (ref->use == IPA_REF_ALIAS) | |
336 node2 = dyn_cast <cgraph_node *> (ref->referring); | |
337 } | |
338 if (!node2) | |
339 break; | |
340 if (!node2->aux) | |
341 { | |
342 stack[++stack_size].node = node2; | |
343 stack[stack_size].edge = node2->callers; | |
344 stack[stack_size].ref = 0; | |
345 node2->aux = (void *)(size_t)1; | |
346 } | |
347 } | |
348 order[order_pos++] = stack[stack_size--].node; | |
349 } | |
350 } | |
351 free (stack); | |
352 FOR_EACH_FUNCTION (node) | |
353 node->aux = NULL; | |
354 return order_pos; | |
355 } | |
356 | |
357 | |
0 | 358 |
359 /* Given a memory reference T, will return the variable at the bottom | |
111 | 360 of the access. Unlike get_base_address, this will recurse through |
0 | 361 INDIRECT_REFS. */ |
362 | |
363 tree | |
364 get_base_var (tree t) | |
365 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
366 while (!SSA_VAR_P (t) |
0 | 367 && (!CONSTANT_CLASS_P (t)) |
368 && TREE_CODE (t) != LABEL_DECL | |
369 && TREE_CODE (t) != FUNCTION_DECL | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
370 && TREE_CODE (t) != CONST_DECL |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
371 && TREE_CODE (t) != CONSTRUCTOR) |
0 | 372 { |
373 t = TREE_OPERAND (t, 0); | |
374 } | |
375 return t; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
376 } |
0 | 377 |
111 | 378 |
379 /* SRC and DST are going to be merged. Take SRC's profile and merge it into | |
380 DST so it is not going to be lost. Possibly destroy SRC's body on the way | |
381 unless PRESERVE_BODY is set. */ | |
382 | |
383 void | |
384 ipa_merge_profiles (struct cgraph_node *dst, | |
385 struct cgraph_node *src, | |
386 bool preserve_body) | |
387 { | |
388 tree oldsrcdecl = src->decl; | |
389 struct function *srccfun, *dstcfun; | |
390 bool match = true; | |
391 | |
392 if (!src->definition | |
393 || !dst->definition) | |
394 return; | |
395 if (src->frequency < dst->frequency) | |
396 src->frequency = dst->frequency; | |
397 | |
398 /* Time profiles are merged. */ | |
399 if (dst->tp_first_run > src->tp_first_run && src->tp_first_run) | |
400 dst->tp_first_run = src->tp_first_run; | |
401 | |
402 if (src->profile_id && !dst->profile_id) | |
403 dst->profile_id = src->profile_id; | |
404 | |
405 /* FIXME when we merge in unknown profile, we ought to set counts as | |
406 unsafe. */ | |
407 if (!src->count.initialized_p ()) | |
408 return; | |
409 if (symtab->dump_file) | |
410 { | |
411 fprintf (symtab->dump_file, "Merging profiles of %s to %s\n", | |
412 src->dump_name (), dst->dump_name ()); | |
413 } | |
414 if (dst->count.initialized_p ()) | |
415 dst->count += src->count; | |
416 else | |
417 dst->count = src->count; | |
418 | |
419 /* This is ugly. We need to get both function bodies into memory. | |
420 If declaration is merged, we need to duplicate it to be able | |
421 to load body that is being replaced. This makes symbol table | |
422 temporarily inconsistent. */ | |
423 if (src->decl == dst->decl) | |
424 { | |
425 struct lto_in_decl_state temp; | |
426 struct lto_in_decl_state *state; | |
427 | |
428 /* We are going to move the decl, we want to remove its file decl data. | |
429 and link these with the new decl. */ | |
430 temp.fn_decl = src->decl; | |
431 lto_in_decl_state **slot | |
432 = src->lto_file_data->function_decl_states->find_slot (&temp, | |
433 NO_INSERT); | |
434 state = *slot; | |
435 src->lto_file_data->function_decl_states->clear_slot (slot); | |
436 gcc_assert (state); | |
437 | |
438 /* Duplicate the decl and be sure it does not link into body of DST. */ | |
439 src->decl = copy_node (src->decl); | |
440 DECL_STRUCT_FUNCTION (src->decl) = NULL; | |
441 DECL_ARGUMENTS (src->decl) = NULL; | |
442 DECL_INITIAL (src->decl) = NULL; | |
443 DECL_RESULT (src->decl) = NULL; | |
444 | |
445 /* Associate the decl state with new declaration, so LTO streamer | |
446 can look it up. */ | |
447 state->fn_decl = src->decl; | |
448 slot | |
449 = src->lto_file_data->function_decl_states->find_slot (state, INSERT); | |
450 gcc_assert (!*slot); | |
451 *slot = state; | |
452 } | |
453 src->get_untransformed_body (); | |
454 dst->get_untransformed_body (); | |
455 srccfun = DECL_STRUCT_FUNCTION (src->decl); | |
456 dstcfun = DECL_STRUCT_FUNCTION (dst->decl); | |
457 if (n_basic_blocks_for_fn (srccfun) | |
458 != n_basic_blocks_for_fn (dstcfun)) | |
459 { | |
460 if (symtab->dump_file) | |
461 fprintf (symtab->dump_file, | |
462 "Giving up; number of basic block mismatch.\n"); | |
463 match = false; | |
464 } | |
465 else if (last_basic_block_for_fn (srccfun) | |
466 != last_basic_block_for_fn (dstcfun)) | |
467 { | |
468 if (symtab->dump_file) | |
469 fprintf (symtab->dump_file, | |
470 "Giving up; last block mismatch.\n"); | |
471 match = false; | |
472 } | |
473 else | |
474 { | |
475 basic_block srcbb, dstbb; | |
476 | |
477 FOR_ALL_BB_FN (srcbb, srccfun) | |
478 { | |
479 unsigned int i; | |
480 | |
481 dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index); | |
482 if (dstbb == NULL) | |
483 { | |
484 if (symtab->dump_file) | |
485 fprintf (symtab->dump_file, | |
486 "No matching block for bb %i.\n", | |
487 srcbb->index); | |
488 match = false; | |
489 break; | |
490 } | |
491 if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs)) | |
492 { | |
493 if (symtab->dump_file) | |
494 fprintf (symtab->dump_file, | |
495 "Edge count mistmatch for bb %i.\n", | |
496 srcbb->index); | |
497 match = false; | |
498 break; | |
499 } | |
500 for (i = 0; i < EDGE_COUNT (srcbb->succs); i++) | |
501 { | |
502 edge srce = EDGE_SUCC (srcbb, i); | |
503 edge dste = EDGE_SUCC (dstbb, i); | |
504 if (srce->dest->index != dste->dest->index) | |
505 { | |
506 if (symtab->dump_file) | |
507 fprintf (symtab->dump_file, | |
508 "Succ edge mistmatch for bb %i.\n", | |
509 srce->dest->index); | |
510 match = false; | |
511 break; | |
512 } | |
513 } | |
514 } | |
515 } | |
516 if (match) | |
517 { | |
518 struct cgraph_edge *e, *e2; | |
519 basic_block srcbb, dstbb; | |
520 | |
521 /* TODO: merge also statement histograms. */ | |
522 FOR_ALL_BB_FN (srcbb, srccfun) | |
523 { | |
524 unsigned int i; | |
525 | |
526 dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index); | |
527 if (!dstbb->count.initialized_p ()) | |
528 { | |
529 dstbb->count = srcbb->count; | |
530 for (i = 0; i < EDGE_COUNT (srcbb->succs); i++) | |
531 { | |
532 edge srce = EDGE_SUCC (srcbb, i); | |
533 edge dste = EDGE_SUCC (dstbb, i); | |
534 if (srce->probability.initialized_p ()) | |
535 dste->probability = srce->probability; | |
536 } | |
537 } | |
538 else if (srcbb->count.initialized_p ()) | |
539 { | |
540 for (i = 0; i < EDGE_COUNT (srcbb->succs); i++) | |
541 { | |
542 edge srce = EDGE_SUCC (srcbb, i); | |
543 edge dste = EDGE_SUCC (dstbb, i); | |
544 dste->probability = | |
545 dste->probability * dstbb->count.probability_in (dstbb->count + srcbb->count) | |
546 + srce->probability * srcbb->count.probability_in (dstbb->count + srcbb->count); | |
547 } | |
548 dstbb->count += srcbb->count; | |
549 } | |
550 } | |
551 push_cfun (dstcfun); | |
552 counts_to_freqs (); | |
553 compute_function_frequency (); | |
554 pop_cfun (); | |
555 for (e = dst->callees; e; e = e->next_callee) | |
556 { | |
557 if (e->speculative) | |
558 continue; | |
559 e->count = gimple_bb (e->call_stmt)->count; | |
560 e->frequency = compute_call_stmt_bb_frequency | |
561 (dst->decl, | |
562 gimple_bb (e->call_stmt)); | |
563 } | |
564 for (e = dst->indirect_calls, e2 = src->indirect_calls; e; | |
565 e2 = (e2 ? e2->next_callee : NULL), e = e->next_callee) | |
566 { | |
567 profile_count count = gimple_bb (e->call_stmt)->count; | |
568 int freq = compute_call_stmt_bb_frequency | |
569 (dst->decl, | |
570 gimple_bb (e->call_stmt)); | |
571 /* When call is speculative, we need to re-distribute probabilities | |
572 the same way as they was. This is not really correct because | |
573 in the other copy the speculation may differ; but probably it | |
574 is not really worth the effort. */ | |
575 if (e->speculative) | |
576 { | |
577 cgraph_edge *direct, *indirect; | |
578 cgraph_edge *direct2 = NULL, *indirect2 = NULL; | |
579 ipa_ref *ref; | |
580 | |
581 e->speculative_call_info (direct, indirect, ref); | |
582 gcc_assert (e == indirect); | |
583 if (e2 && e2->speculative) | |
584 e2->speculative_call_info (direct2, indirect2, ref); | |
585 if (indirect->count > profile_count::zero () | |
586 || direct->count > profile_count::zero ()) | |
587 { | |
588 /* We should mismatch earlier if there is no matching | |
589 indirect edge. */ | |
590 if (!e2) | |
591 { | |
592 if (dump_file) | |
593 fprintf (dump_file, | |
594 "Mismatch in merging indirect edges\n"); | |
595 } | |
596 else if (!e2->speculative) | |
597 indirect->count += e2->count; | |
598 else if (e2->speculative) | |
599 { | |
600 if (DECL_ASSEMBLER_NAME (direct2->callee->decl) | |
601 != DECL_ASSEMBLER_NAME (direct->callee->decl)) | |
602 { | |
603 if (direct2->count >= direct->count) | |
604 { | |
605 direct->redirect_callee (direct2->callee); | |
606 indirect->count += indirect2->count | |
607 + direct->count; | |
608 direct->count = direct2->count; | |
609 } | |
610 else | |
611 indirect->count += indirect2->count + direct2->count; | |
612 } | |
613 else | |
614 { | |
615 direct->count += direct2->count; | |
616 indirect->count += indirect2->count; | |
617 } | |
618 } | |
619 int prob = direct->count.probability_in (direct->count | |
620 + indirect->count). | |
621 to_reg_br_prob_base (); | |
622 direct->frequency = RDIV (freq * prob, REG_BR_PROB_BASE); | |
623 indirect->frequency = RDIV (freq * (REG_BR_PROB_BASE - prob), | |
624 REG_BR_PROB_BASE); | |
625 } | |
626 else | |
627 /* At the moment we should have only profile feedback based | |
628 speculations when merging. */ | |
629 gcc_unreachable (); | |
630 } | |
631 else if (e2 && e2->speculative) | |
632 { | |
633 cgraph_edge *direct, *indirect; | |
634 ipa_ref *ref; | |
635 | |
636 e2->speculative_call_info (direct, indirect, ref); | |
637 e->count = count; | |
638 e->frequency = freq; | |
639 int prob = direct->count.probability_in (e->count) | |
640 .to_reg_br_prob_base (); | |
641 e->make_speculative (direct->callee, direct->count, | |
642 RDIV (freq * prob, REG_BR_PROB_BASE)); | |
643 } | |
644 else | |
645 { | |
646 e->count = count; | |
647 e->frequency = freq; | |
648 } | |
649 } | |
650 if (!preserve_body) | |
651 src->release_body (); | |
652 ipa_update_overall_fn_summary (dst); | |
653 } | |
654 /* TODO: if there is no match, we can scale up. */ | |
655 src->decl = oldsrcdecl; | |
656 } | |
657 | |
658 /* Return true if call to DEST is known to be self-recusive call withing FUNC. */ | |
659 | |
660 bool | |
661 recursive_call_p (tree func, tree dest) | |
662 { | |
663 struct cgraph_node *dest_node = cgraph_node::get_create (dest); | |
664 struct cgraph_node *cnode = cgraph_node::get_create (func); | |
665 ipa_ref *alias; | |
666 enum availability avail; | |
667 | |
668 gcc_assert (!cnode->alias); | |
669 if (cnode != dest_node->ultimate_alias_target (&avail)) | |
670 return false; | |
671 if (avail >= AVAIL_AVAILABLE) | |
672 return true; | |
673 if (!dest_node->semantically_equivalent_p (cnode)) | |
674 return false; | |
675 /* If there is only one way to call the fuction or we know all of them | |
676 are semantically equivalent, we still can consider call recursive. */ | |
677 FOR_EACH_ALIAS (cnode, alias) | |
678 if (!dest_node->semantically_equivalent_p (alias->referring)) | |
679 return false; | |
680 return true; | |
681 } |