comparison gcc/lto-wpa-fixup.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents
children
comparison
equal deleted inserted replaced
52:c156f1bd5cd9 55:77e2b8dfacca
1 /* Write and read any fix-up information generated by the WPA mode.
2
3 Copyright 2009 Free Software Foundation, Inc.
4 Contributed by Doug Kwan <dougkwan@google.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "toplev.h"
27 #include "tree.h"
28 #include "expr.h"
29 #include "flags.h"
30 #include "cgraph.h"
31 #include "function.h"
32 #include "diagnostic.h"
33 #include "vec.h"
34 #include "bitmap.h"
35 #include "timevar.h"
36 #include "tree-flow.h"
37 #include "tree-pass.h"
38 #include "lto-streamer.h"
39
40 /* LTO fix-up.
41
42 In WPA mode, LTO cannot access function bodies. Some modifications in
43 IR require additional updates in function bodies, which are not possible
44 in WPA mode. So we write out information about these modifications for
45 LTRANS to fix up the function bodies accordingly. */
46
47 /* The vectors records function DECLs having multiple copies with different
48 exception throwing attributes. We do not mark a DECL if all copies of it
49 have the same exception throwing attribute. */
50 static bitmap lto_nothrow_fndecls;
51
52 /* We need to fix up GIMPLE bodies due to changes in exception setting.
53 Consider this example:
54
55 a.h:
56 class a {
57 public:
58 a();
59 ~a();
60 };
61
62 main.cc:
63 #include "a.h"
64
65 int
66 main (int argc, char **argv)
67 {
68 a x;
69 return 0;
70 }
71
72 a.cc:
73 #include "a.h"
74 a::a() {}
75 a::~a() {}
76
77 When main.cc is compiled, gcc only sees the constructor declaration, so
78 the constructor and hence the call to it are marked as exception throwing.
79 When a.cc is compiled, the body of the constructor is available and is
80 obviously not exception throwing. Thus DECL of a::a in a.o has the NOTHROW
81 attribute. When LTO runs, two DECLs of a::a with different exception
82 attributes are merged. We want the merged DECL to be not exception
83 throwing for better generated code. To do that, we need to fix up any
84 function calls that have been marked as exception throwing. */
85
86 /* Fix up all the call statements whose target fndecls might have changed
87 to NOTHROW. Note that this problem is not WPA specific. We can also
88 run into this problem in normal LTO with multiple input files. */
89
90 void
91 lto_fixup_nothrow_decls (void)
92 {
93 struct cgraph_node *node;
94 struct cgraph_edge *edge;
95 struct function *caller_function;
96 gimple call_stmt;
97
98 /* Quit if we are in WPA mode or have not marked any DECLs. */
99 if (flag_wpa || !lto_nothrow_fndecls)
100 return;
101
102 /* For each node that has been marked, go over all call edges to it. */
103 for (node = cgraph_nodes; node; node = node->next)
104 if (bitmap_bit_p (lto_nothrow_fndecls, DECL_UID (node->decl)))
105 {
106 gcc_assert (TREE_NOTHROW (node->decl));
107 for (edge = node->callers; edge; edge = edge->next_caller)
108 {
109 caller_function = DECL_STRUCT_FUNCTION (edge->caller->decl);
110 call_stmt = edge->call_stmt;
111 gcc_assert (call_stmt);
112 if (lookup_stmt_eh_lp_fn (caller_function, call_stmt) != 0)
113 remove_stmt_from_eh_lp_fn (caller_function, call_stmt);
114 }
115 }
116 }
117
118 /* Mark FNDECL as becoming not exception throwing. */
119
120 void
121 lto_mark_nothrow_fndecl (tree fndecl)
122 {
123 gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
124 if (!lto_nothrow_fndecls)
125 lto_nothrow_fndecls = lto_bitmap_alloc ();
126
127 bitmap_set_bit (lto_nothrow_fndecls, DECL_UID (fndecl));
128 }
129
130 /* Write out fix-up information. Currently the only WPA fix-up
131 information is the list of DECLs marked as not exception throwing. SET
132 is a cgraph node set whose fix-up information is to be written. */
133
134 static void
135 lto_output_wpa_fixup (cgraph_node_set set)
136 {
137 struct lto_simple_output_block *ob;
138 cgraph_node_set_iterator csi;
139 tree fndecl;
140 bitmap seen_decls;
141 VEC(tree, heap) *decls = NULL;
142 unsigned HOST_WIDE_INT i, count;
143
144 ob = lto_create_simple_output_block (LTO_section_wpa_fixup);
145
146 /* Accumulate the DECLs to be written out. Since we do not want
147 duplicates, we need to use a bitmap and a vector to save the
148 DECLs we want. Note that we need to check if lto_nothrow_fndecls
149 is NULL. This happens when no DECL has been marked. */
150 seen_decls = lto_bitmap_alloc ();
151 if (lto_nothrow_fndecls)
152 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
153 {
154 struct cgraph_edge *e;
155 struct cgraph_node *n;
156
157 n = csi_node (csi);
158 fndecl = n->decl;
159
160 /* Check if the N's function is in the set of nothrow functions. */
161 if (!bitmap_bit_p (seen_decls, DECL_UID (fndecl)))
162 {
163 bitmap_set_bit (seen_decls, (DECL_UID (fndecl)));
164 if (bitmap_bit_p (lto_nothrow_fndecls, DECL_UID (fndecl)))
165 VEC_safe_push (tree, heap, decls, fndecl);
166 }
167
168 /* Now check the callees and also add them if they are nothrow. This
169 is needed because node N may end up in a different partition than
170 its callees. In which case, when the file holding N is compiled,
171 the calls it makes to nothrow functions will not be fixed up,
172 causing verification issues. */
173 for (e = n->callees; e; e = e->next_callee)
174 {
175 fndecl = e->callee->decl;
176 if (!bitmap_bit_p (seen_decls, DECL_UID (fndecl)))
177 {
178 bitmap_set_bit (seen_decls, (DECL_UID (fndecl)));
179 if (bitmap_bit_p (lto_nothrow_fndecls, DECL_UID (fndecl)))
180 VEC_safe_push (tree, heap, decls, fndecl);
181 }
182 }
183 }
184
185 /* Write out number of DECLs, followed by the DECLs. */
186 count = VEC_length (tree, decls);
187 lto_output_uleb128_stream (ob->main_stream, count);
188 for (i = 0; i < count; i++)
189 {
190 fndecl = VEC_index (tree, decls, i);
191 lto_output_fn_decl_index (ob->decl_state, ob->main_stream, fndecl);
192 }
193
194 /* Release resources. */
195 lto_destroy_simple_output_block (ob);
196 VEC_free(tree, heap, decls);
197 lto_bitmap_free (seen_decls);
198 }
199
200 /* Read in WPA fix-up information from one file. FILE_DATA points to
201 DECL information of the file where as IB is the input block for the
202 WPA fix-up section. */
203
204 static void
205 lto_input_wpa_fixup_1 (struct lto_file_decl_data *file_data,
206 struct lto_input_block *ib)
207 {
208 unsigned HOST_WIDE_INT i, count, decl_index;
209 tree fndecl;
210
211 count = lto_input_uleb128 (ib);
212 for (i = 0; i < count; i++)
213 {
214 decl_index = lto_input_uleb128 (ib);
215 fndecl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
216 lto_mark_nothrow_fndecl (fndecl);
217 }
218 }
219
220 /* Read in WPA fix-up information. */
221
222 static void
223 lto_input_wpa_fixup (void)
224 {
225 struct lto_file_decl_data ** file_data_vec
226 = lto_get_file_decl_data ();
227 struct lto_file_decl_data * file_data;
228 int i = 0;
229
230 /* Fix up information is only used in LTRANS mode. */
231 if (!flag_ltrans)
232 return;
233
234 while ((file_data = file_data_vec[i++]))
235 {
236 const char *data;
237 size_t len;
238 struct lto_input_block *ib
239 = lto_create_simple_input_block (file_data, LTO_section_wpa_fixup,
240 &data, &len);
241
242 lto_input_wpa_fixup_1 (file_data, ib);
243 lto_destroy_simple_input_block (file_data, LTO_section_wpa_fixup, ib,
244 data, len);
245 }
246 }
247
248 /* Gate function for all lto streaming passes. */
249
250 static bool
251 gate_wpa_fixup (void)
252 {
253 return (flag_wpa || flag_ltrans) && gate_lto_out ();
254 }
255
256 struct ipa_opt_pass_d pass_ipa_lto_wpa_fixup =
257 {
258 {
259 IPA_PASS,
260 "lto_wpa_fixup", /* name */
261 gate_wpa_fixup, /* gate */
262 NULL, /* execute */
263 NULL, /* sub */
264 NULL, /* next */
265 0, /* static_pass_number */
266 TV_WHOPR_WPA_FIXUP, /* tv_id */
267 0, /* properties_required */
268 0, /* properties_provided */
269 0, /* properties_destroyed */
270 0, /* todo_flags_start */
271 TODO_dump_func /* todo_flags_finish */
272 },
273 NULL, /* generate_summary */
274 lto_output_wpa_fixup, /* write_summary */
275 lto_input_wpa_fixup, /* read_summary */
276 NULL, /* function_read_summary */
277 NULL, /* stmt_fixup */
278 0, /* TODOs */
279 NULL, /* function_transform */
280 NULL /* variable_transform */
281 };
282