annotate gcc/ipa-utils.c @ 127:4c56639505ff

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