annotate gcc/ipa-utils.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
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.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2005-2018 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;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
89 splay_tree_remove (env->nodes_marked_new, v->get_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,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
198 (splay_tree_key)node->get_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. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
407 if (!src->count.initialized_p ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
408 || !(src->count.ipa () == src->count))
111
kono
parents: 55
diff changeset
409 return;
kono
parents: 55
diff changeset
410 if (symtab->dump_file)
kono
parents: 55
diff changeset
411 {
kono
parents: 55
diff changeset
412 fprintf (symtab->dump_file, "Merging profiles of %s to %s\n",
kono
parents: 55
diff changeset
413 src->dump_name (), dst->dump_name ());
kono
parents: 55
diff changeset
414 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
415 if (dst->count.initialized_p () && dst->count.ipa () == dst->count)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
416 dst->count += src->count.ipa ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
417 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
418 dst->count = src->count.ipa ();
111
kono
parents: 55
diff changeset
419
kono
parents: 55
diff changeset
420 /* This is ugly. We need to get both function bodies into memory.
kono
parents: 55
diff changeset
421 If declaration is merged, we need to duplicate it to be able
kono
parents: 55
diff changeset
422 to load body that is being replaced. This makes symbol table
kono
parents: 55
diff changeset
423 temporarily inconsistent. */
kono
parents: 55
diff changeset
424 if (src->decl == dst->decl)
kono
parents: 55
diff changeset
425 {
kono
parents: 55
diff changeset
426 struct lto_in_decl_state temp;
kono
parents: 55
diff changeset
427 struct lto_in_decl_state *state;
kono
parents: 55
diff changeset
428
kono
parents: 55
diff changeset
429 /* We are going to move the decl, we want to remove its file decl data.
kono
parents: 55
diff changeset
430 and link these with the new decl. */
kono
parents: 55
diff changeset
431 temp.fn_decl = src->decl;
kono
parents: 55
diff changeset
432 lto_in_decl_state **slot
kono
parents: 55
diff changeset
433 = src->lto_file_data->function_decl_states->find_slot (&temp,
kono
parents: 55
diff changeset
434 NO_INSERT);
kono
parents: 55
diff changeset
435 state = *slot;
kono
parents: 55
diff changeset
436 src->lto_file_data->function_decl_states->clear_slot (slot);
kono
parents: 55
diff changeset
437 gcc_assert (state);
kono
parents: 55
diff changeset
438
kono
parents: 55
diff changeset
439 /* Duplicate the decl and be sure it does not link into body of DST. */
kono
parents: 55
diff changeset
440 src->decl = copy_node (src->decl);
kono
parents: 55
diff changeset
441 DECL_STRUCT_FUNCTION (src->decl) = NULL;
kono
parents: 55
diff changeset
442 DECL_ARGUMENTS (src->decl) = NULL;
kono
parents: 55
diff changeset
443 DECL_INITIAL (src->decl) = NULL;
kono
parents: 55
diff changeset
444 DECL_RESULT (src->decl) = NULL;
kono
parents: 55
diff changeset
445
kono
parents: 55
diff changeset
446 /* Associate the decl state with new declaration, so LTO streamer
kono
parents: 55
diff changeset
447 can look it up. */
kono
parents: 55
diff changeset
448 state->fn_decl = src->decl;
kono
parents: 55
diff changeset
449 slot
kono
parents: 55
diff changeset
450 = src->lto_file_data->function_decl_states->find_slot (state, INSERT);
kono
parents: 55
diff changeset
451 gcc_assert (!*slot);
kono
parents: 55
diff changeset
452 *slot = state;
kono
parents: 55
diff changeset
453 }
kono
parents: 55
diff changeset
454 src->get_untransformed_body ();
kono
parents: 55
diff changeset
455 dst->get_untransformed_body ();
kono
parents: 55
diff changeset
456 srccfun = DECL_STRUCT_FUNCTION (src->decl);
kono
parents: 55
diff changeset
457 dstcfun = DECL_STRUCT_FUNCTION (dst->decl);
kono
parents: 55
diff changeset
458 if (n_basic_blocks_for_fn (srccfun)
kono
parents: 55
diff changeset
459 != n_basic_blocks_for_fn (dstcfun))
kono
parents: 55
diff changeset
460 {
kono
parents: 55
diff changeset
461 if (symtab->dump_file)
kono
parents: 55
diff changeset
462 fprintf (symtab->dump_file,
kono
parents: 55
diff changeset
463 "Giving up; number of basic block mismatch.\n");
kono
parents: 55
diff changeset
464 match = false;
kono
parents: 55
diff changeset
465 }
kono
parents: 55
diff changeset
466 else if (last_basic_block_for_fn (srccfun)
kono
parents: 55
diff changeset
467 != last_basic_block_for_fn (dstcfun))
kono
parents: 55
diff changeset
468 {
kono
parents: 55
diff changeset
469 if (symtab->dump_file)
kono
parents: 55
diff changeset
470 fprintf (symtab->dump_file,
kono
parents: 55
diff changeset
471 "Giving up; last block mismatch.\n");
kono
parents: 55
diff changeset
472 match = false;
kono
parents: 55
diff changeset
473 }
kono
parents: 55
diff changeset
474 else
kono
parents: 55
diff changeset
475 {
kono
parents: 55
diff changeset
476 basic_block srcbb, dstbb;
kono
parents: 55
diff changeset
477
kono
parents: 55
diff changeset
478 FOR_ALL_BB_FN (srcbb, srccfun)
kono
parents: 55
diff changeset
479 {
kono
parents: 55
diff changeset
480 unsigned int i;
kono
parents: 55
diff changeset
481
kono
parents: 55
diff changeset
482 dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
kono
parents: 55
diff changeset
483 if (dstbb == NULL)
kono
parents: 55
diff changeset
484 {
kono
parents: 55
diff changeset
485 if (symtab->dump_file)
kono
parents: 55
diff changeset
486 fprintf (symtab->dump_file,
kono
parents: 55
diff changeset
487 "No matching block for bb %i.\n",
kono
parents: 55
diff changeset
488 srcbb->index);
kono
parents: 55
diff changeset
489 match = false;
kono
parents: 55
diff changeset
490 break;
kono
parents: 55
diff changeset
491 }
kono
parents: 55
diff changeset
492 if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs))
kono
parents: 55
diff changeset
493 {
kono
parents: 55
diff changeset
494 if (symtab->dump_file)
kono
parents: 55
diff changeset
495 fprintf (symtab->dump_file,
kono
parents: 55
diff changeset
496 "Edge count mistmatch for bb %i.\n",
kono
parents: 55
diff changeset
497 srcbb->index);
kono
parents: 55
diff changeset
498 match = false;
kono
parents: 55
diff changeset
499 break;
kono
parents: 55
diff changeset
500 }
kono
parents: 55
diff changeset
501 for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
kono
parents: 55
diff changeset
502 {
kono
parents: 55
diff changeset
503 edge srce = EDGE_SUCC (srcbb, i);
kono
parents: 55
diff changeset
504 edge dste = EDGE_SUCC (dstbb, i);
kono
parents: 55
diff changeset
505 if (srce->dest->index != dste->dest->index)
kono
parents: 55
diff changeset
506 {
kono
parents: 55
diff changeset
507 if (symtab->dump_file)
kono
parents: 55
diff changeset
508 fprintf (symtab->dump_file,
kono
parents: 55
diff changeset
509 "Succ edge mistmatch for bb %i.\n",
kono
parents: 55
diff changeset
510 srce->dest->index);
kono
parents: 55
diff changeset
511 match = false;
kono
parents: 55
diff changeset
512 break;
kono
parents: 55
diff changeset
513 }
kono
parents: 55
diff changeset
514 }
kono
parents: 55
diff changeset
515 }
kono
parents: 55
diff changeset
516 }
kono
parents: 55
diff changeset
517 if (match)
kono
parents: 55
diff changeset
518 {
kono
parents: 55
diff changeset
519 struct cgraph_edge *e, *e2;
kono
parents: 55
diff changeset
520 basic_block srcbb, dstbb;
kono
parents: 55
diff changeset
521
kono
parents: 55
diff changeset
522 /* TODO: merge also statement histograms. */
kono
parents: 55
diff changeset
523 FOR_ALL_BB_FN (srcbb, srccfun)
kono
parents: 55
diff changeset
524 {
kono
parents: 55
diff changeset
525 unsigned int i;
kono
parents: 55
diff changeset
526
kono
parents: 55
diff changeset
527 dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
528
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
529 /* Either sum the profiles if both are IPA and not global0, or
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
530 pick more informative one (that is nonzero IPA if other is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
531 uninitialized, guessed or global0). */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
532 if (!dstbb->count.ipa ().initialized_p ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
533 || (dstbb->count.ipa () == profile_count::zero ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
534 && (srcbb->count.ipa ().initialized_p ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
535 && !(srcbb->count.ipa () == profile_count::zero ()))))
111
kono
parents: 55
diff changeset
536 {
kono
parents: 55
diff changeset
537 dstbb->count = srcbb->count;
kono
parents: 55
diff changeset
538 for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
kono
parents: 55
diff changeset
539 {
kono
parents: 55
diff changeset
540 edge srce = EDGE_SUCC (srcbb, i);
kono
parents: 55
diff changeset
541 edge dste = EDGE_SUCC (dstbb, i);
kono
parents: 55
diff changeset
542 if (srce->probability.initialized_p ())
kono
parents: 55
diff changeset
543 dste->probability = srce->probability;
kono
parents: 55
diff changeset
544 }
kono
parents: 55
diff changeset
545 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
546 else if (srcbb->count.ipa ().initialized_p ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
547 && !(srcbb->count.ipa () == profile_count::zero ()))
111
kono
parents: 55
diff changeset
548 {
kono
parents: 55
diff changeset
549 for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
kono
parents: 55
diff changeset
550 {
kono
parents: 55
diff changeset
551 edge srce = EDGE_SUCC (srcbb, i);
kono
parents: 55
diff changeset
552 edge dste = EDGE_SUCC (dstbb, i);
kono
parents: 55
diff changeset
553 dste->probability =
kono
parents: 55
diff changeset
554 dste->probability * dstbb->count.probability_in (dstbb->count + srcbb->count)
kono
parents: 55
diff changeset
555 + srce->probability * srcbb->count.probability_in (dstbb->count + srcbb->count);
kono
parents: 55
diff changeset
556 }
kono
parents: 55
diff changeset
557 dstbb->count += srcbb->count;
kono
parents: 55
diff changeset
558 }
kono
parents: 55
diff changeset
559 }
kono
parents: 55
diff changeset
560 push_cfun (dstcfun);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
561 update_max_bb_count ();
111
kono
parents: 55
diff changeset
562 compute_function_frequency ();
kono
parents: 55
diff changeset
563 pop_cfun ();
kono
parents: 55
diff changeset
564 for (e = dst->callees; e; e = e->next_callee)
kono
parents: 55
diff changeset
565 {
kono
parents: 55
diff changeset
566 if (e->speculative)
kono
parents: 55
diff changeset
567 continue;
kono
parents: 55
diff changeset
568 e->count = gimple_bb (e->call_stmt)->count;
kono
parents: 55
diff changeset
569 }
kono
parents: 55
diff changeset
570 for (e = dst->indirect_calls, e2 = src->indirect_calls; e;
kono
parents: 55
diff changeset
571 e2 = (e2 ? e2->next_callee : NULL), e = e->next_callee)
kono
parents: 55
diff changeset
572 {
kono
parents: 55
diff changeset
573 profile_count count = gimple_bb (e->call_stmt)->count;
kono
parents: 55
diff changeset
574 /* When call is speculative, we need to re-distribute probabilities
kono
parents: 55
diff changeset
575 the same way as they was. This is not really correct because
kono
parents: 55
diff changeset
576 in the other copy the speculation may differ; but probably it
kono
parents: 55
diff changeset
577 is not really worth the effort. */
kono
parents: 55
diff changeset
578 if (e->speculative)
kono
parents: 55
diff changeset
579 {
kono
parents: 55
diff changeset
580 cgraph_edge *direct, *indirect;
kono
parents: 55
diff changeset
581 cgraph_edge *direct2 = NULL, *indirect2 = NULL;
kono
parents: 55
diff changeset
582 ipa_ref *ref;
kono
parents: 55
diff changeset
583
kono
parents: 55
diff changeset
584 e->speculative_call_info (direct, indirect, ref);
kono
parents: 55
diff changeset
585 gcc_assert (e == indirect);
kono
parents: 55
diff changeset
586 if (e2 && e2->speculative)
kono
parents: 55
diff changeset
587 e2->speculative_call_info (direct2, indirect2, ref);
kono
parents: 55
diff changeset
588 if (indirect->count > profile_count::zero ()
kono
parents: 55
diff changeset
589 || direct->count > profile_count::zero ())
kono
parents: 55
diff changeset
590 {
kono
parents: 55
diff changeset
591 /* We should mismatch earlier if there is no matching
kono
parents: 55
diff changeset
592 indirect edge. */
kono
parents: 55
diff changeset
593 if (!e2)
kono
parents: 55
diff changeset
594 {
kono
parents: 55
diff changeset
595 if (dump_file)
kono
parents: 55
diff changeset
596 fprintf (dump_file,
kono
parents: 55
diff changeset
597 "Mismatch in merging indirect edges\n");
kono
parents: 55
diff changeset
598 }
kono
parents: 55
diff changeset
599 else if (!e2->speculative)
kono
parents: 55
diff changeset
600 indirect->count += e2->count;
kono
parents: 55
diff changeset
601 else if (e2->speculative)
kono
parents: 55
diff changeset
602 {
kono
parents: 55
diff changeset
603 if (DECL_ASSEMBLER_NAME (direct2->callee->decl)
kono
parents: 55
diff changeset
604 != DECL_ASSEMBLER_NAME (direct->callee->decl))
kono
parents: 55
diff changeset
605 {
kono
parents: 55
diff changeset
606 if (direct2->count >= direct->count)
kono
parents: 55
diff changeset
607 {
kono
parents: 55
diff changeset
608 direct->redirect_callee (direct2->callee);
kono
parents: 55
diff changeset
609 indirect->count += indirect2->count
kono
parents: 55
diff changeset
610 + direct->count;
kono
parents: 55
diff changeset
611 direct->count = direct2->count;
kono
parents: 55
diff changeset
612 }
kono
parents: 55
diff changeset
613 else
kono
parents: 55
diff changeset
614 indirect->count += indirect2->count + direct2->count;
kono
parents: 55
diff changeset
615 }
kono
parents: 55
diff changeset
616 else
kono
parents: 55
diff changeset
617 {
kono
parents: 55
diff changeset
618 direct->count += direct2->count;
kono
parents: 55
diff changeset
619 indirect->count += indirect2->count;
kono
parents: 55
diff changeset
620 }
kono
parents: 55
diff changeset
621 }
kono
parents: 55
diff changeset
622 }
kono
parents: 55
diff changeset
623 else
kono
parents: 55
diff changeset
624 /* At the moment we should have only profile feedback based
kono
parents: 55
diff changeset
625 speculations when merging. */
kono
parents: 55
diff changeset
626 gcc_unreachable ();
kono
parents: 55
diff changeset
627 }
kono
parents: 55
diff changeset
628 else if (e2 && e2->speculative)
kono
parents: 55
diff changeset
629 {
kono
parents: 55
diff changeset
630 cgraph_edge *direct, *indirect;
kono
parents: 55
diff changeset
631 ipa_ref *ref;
kono
parents: 55
diff changeset
632
kono
parents: 55
diff changeset
633 e2->speculative_call_info (direct, indirect, ref);
kono
parents: 55
diff changeset
634 e->count = count;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
635 e->make_speculative (direct->callee, direct->count);
111
kono
parents: 55
diff changeset
636 }
kono
parents: 55
diff changeset
637 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
638 e->count = count;
111
kono
parents: 55
diff changeset
639 }
kono
parents: 55
diff changeset
640 if (!preserve_body)
kono
parents: 55
diff changeset
641 src->release_body ();
kono
parents: 55
diff changeset
642 ipa_update_overall_fn_summary (dst);
kono
parents: 55
diff changeset
643 }
kono
parents: 55
diff changeset
644 /* TODO: if there is no match, we can scale up. */
kono
parents: 55
diff changeset
645 src->decl = oldsrcdecl;
kono
parents: 55
diff changeset
646 }
kono
parents: 55
diff changeset
647
kono
parents: 55
diff changeset
648 /* Return true if call to DEST is known to be self-recusive call withing FUNC. */
kono
parents: 55
diff changeset
649
kono
parents: 55
diff changeset
650 bool
kono
parents: 55
diff changeset
651 recursive_call_p (tree func, tree dest)
kono
parents: 55
diff changeset
652 {
kono
parents: 55
diff changeset
653 struct cgraph_node *dest_node = cgraph_node::get_create (dest);
kono
parents: 55
diff changeset
654 struct cgraph_node *cnode = cgraph_node::get_create (func);
kono
parents: 55
diff changeset
655 ipa_ref *alias;
kono
parents: 55
diff changeset
656 enum availability avail;
kono
parents: 55
diff changeset
657
kono
parents: 55
diff changeset
658 gcc_assert (!cnode->alias);
kono
parents: 55
diff changeset
659 if (cnode != dest_node->ultimate_alias_target (&avail))
kono
parents: 55
diff changeset
660 return false;
kono
parents: 55
diff changeset
661 if (avail >= AVAIL_AVAILABLE)
kono
parents: 55
diff changeset
662 return true;
kono
parents: 55
diff changeset
663 if (!dest_node->semantically_equivalent_p (cnode))
kono
parents: 55
diff changeset
664 return false;
kono
parents: 55
diff changeset
665 /* If there is only one way to call the fuction or we know all of them
kono
parents: 55
diff changeset
666 are semantically equivalent, we still can consider call recursive. */
kono
parents: 55
diff changeset
667 FOR_EACH_ALIAS (cnode, alias)
kono
parents: 55
diff changeset
668 if (!dest_node->semantically_equivalent_p (alias->referring))
kono
parents: 55
diff changeset
669 return false;
kono
parents: 55
diff changeset
670 return true;
kono
parents: 55
diff changeset
671 }