Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-prop.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 | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 /* Interprocedural analyses. | 1 /* Interprocedural analyses. |
2 Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. | 2 Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
7 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
31 #include "tree-inline.h" | 31 #include "tree-inline.h" |
32 #include "flags.h" | 32 #include "flags.h" |
33 #include "timevar.h" | 33 #include "timevar.h" |
34 #include "flags.h" | 34 #include "flags.h" |
35 #include "diagnostic.h" | 35 #include "diagnostic.h" |
36 #include "lto-streamer.h" | |
36 | 37 |
37 /* Vector where the parameter infos are actually stored. */ | 38 /* Vector where the parameter infos are actually stored. */ |
38 VEC (ipa_node_params_t, heap) *ipa_node_params_vector; | 39 VEC (ipa_node_params_t, heap) *ipa_node_params_vector; |
39 /* Vector where the parameter infos are actually stored. */ | 40 /* Vector where the parameter infos are actually stored. */ |
40 VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector; | 41 VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector; |
41 | 42 |
42 /* Holders of ipa cgraph hooks: */ | 43 /* Holders of ipa cgraph hooks: */ |
43 static struct cgraph_edge_hook_list *edge_removal_hook_holder; | 44 static struct cgraph_edge_hook_list *edge_removal_hook_holder; |
44 static struct cgraph_node_hook_list *node_removal_hook_holder; | 45 static struct cgraph_node_hook_list *node_removal_hook_holder; |
45 static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; | 46 static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; |
46 static struct cgraph_2node_hook_list *node_duplication_hook_holder; | 47 static struct cgraph_2node_hook_list *node_duplication_hook_holder; |
47 | 48 |
49 /* Add cgraph NODE described by INFO to the worklist WL regardless of whether | |
50 it is in one or not. It should almost never be used directly, as opposed to | |
51 ipa_push_func_to_list. */ | |
52 | |
53 void | |
54 ipa_push_func_to_list_1 (struct ipa_func_list **wl, | |
55 struct cgraph_node *node, | |
56 struct ipa_node_params *info) | |
57 { | |
58 struct ipa_func_list *temp; | |
59 | |
60 info->node_enqueued = 1; | |
61 temp = XCNEW (struct ipa_func_list); | |
62 temp->node = node; | |
63 temp->next = *wl; | |
64 *wl = temp; | |
65 } | |
66 | |
48 /* Initialize worklist to contain all functions. */ | 67 /* Initialize worklist to contain all functions. */ |
49 | 68 |
50 struct ipa_func_list * | 69 struct ipa_func_list * |
51 ipa_init_func_list (void) | 70 ipa_init_func_list (void) |
52 { | 71 { |
55 | 74 |
56 wl = NULL; | 75 wl = NULL; |
57 for (node = cgraph_nodes; node; node = node->next) | 76 for (node = cgraph_nodes; node; node = node->next) |
58 if (node->analyzed) | 77 if (node->analyzed) |
59 { | 78 { |
79 struct ipa_node_params *info = IPA_NODE_REF (node); | |
60 /* Unreachable nodes should have been eliminated before ipcp and | 80 /* Unreachable nodes should have been eliminated before ipcp and |
61 inlining. */ | 81 inlining. */ |
62 gcc_assert (node->needed || node->reachable); | 82 gcc_assert (node->needed || node->reachable); |
63 ipa_push_func_to_list (&wl, node); | 83 ipa_push_func_to_list_1 (&wl, node, info); |
64 } | 84 } |
65 | 85 |
66 return wl; | 86 return wl; |
67 } | 87 } |
68 | 88 |
69 /* Add cgraph node MT to the worklist. Set worklist element WL | 89 /* Remove a function from the worklist WL and return it. */ |
70 to point to MT. */ | |
71 | |
72 void | |
73 ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *mt) | |
74 { | |
75 struct ipa_func_list *temp; | |
76 | |
77 temp = XCNEW (struct ipa_func_list); | |
78 temp->node = mt; | |
79 temp->next = *wl; | |
80 *wl = temp; | |
81 } | |
82 | |
83 /* Remove a function from the worklist. WL points to the first | |
84 element in the list, which is removed. */ | |
85 | 90 |
86 struct cgraph_node * | 91 struct cgraph_node * |
87 ipa_pop_func_from_list (struct ipa_func_list ** wl) | 92 ipa_pop_func_from_list (struct ipa_func_list **wl) |
88 { | 93 { |
94 struct ipa_node_params *info; | |
89 struct ipa_func_list *first; | 95 struct ipa_func_list *first; |
90 struct cgraph_node *return_func; | 96 struct cgraph_node *node; |
91 | 97 |
92 first = *wl; | 98 first = *wl; |
93 *wl = (*wl)->next; | 99 *wl = (*wl)->next; |
94 return_func = first->node; | 100 node = first->node; |
95 free (first); | 101 free (first); |
96 return return_func; | 102 |
103 info = IPA_NODE_REF (node); | |
104 info->node_enqueued = 0; | |
105 return node; | |
97 } | 106 } |
98 | 107 |
99 /* Return index of the formal whose tree is PTREE in function which corresponds | 108 /* Return index of the formal whose tree is PTREE in function which corresponds |
100 to INFO. */ | 109 to INFO. */ |
101 | 110 |
132 info->params[param_num].decl = parm; | 141 info->params[param_num].decl = parm; |
133 param_num++; | 142 param_num++; |
134 } | 143 } |
135 } | 144 } |
136 | 145 |
146 /* Return how many formal parameters FNDECL has. */ | |
147 | |
148 static inline int | |
149 count_formal_params_1 (tree fndecl) | |
150 { | |
151 tree parm; | |
152 int count = 0; | |
153 | |
154 for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) | |
155 count++; | |
156 | |
157 return count; | |
158 } | |
159 | |
137 /* Count number of formal parameters in NOTE. Store the result to the | 160 /* Count number of formal parameters in NOTE. Store the result to the |
138 appropriate field of INFO. */ | 161 appropriate field of INFO. */ |
139 | 162 |
140 static void | 163 static void |
141 ipa_count_formal_params (struct cgraph_node *node, | 164 ipa_count_formal_params (struct cgraph_node *node, |
142 struct ipa_node_params *info) | 165 struct ipa_node_params *info) |
143 { | 166 { |
144 tree fndecl; | |
145 tree fnargs; | |
146 tree parm; | |
147 int param_num; | 167 int param_num; |
148 | 168 |
149 fndecl = node->decl; | 169 param_num = count_formal_params_1 (node->decl); |
150 fnargs = DECL_ARGUMENTS (fndecl); | |
151 param_num = 0; | |
152 for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) | |
153 param_num++; | |
154 ipa_set_param_count (info, param_num); | 170 ipa_set_param_count (info, param_num); |
155 } | 171 } |
156 | 172 |
157 /* Initialize the ipa_node_params structure associated with NODE by counting | 173 /* Initialize the ipa_node_params structure associated with NODE by counting |
158 the function parameters, creating the descriptors and populating their | 174 the function parameters, creating the descriptors and populating their |
170 ipa_get_param_count (info)); | 186 ipa_get_param_count (info)); |
171 ipa_populate_param_decls (node, info); | 187 ipa_populate_param_decls (node, info); |
172 } | 188 } |
173 } | 189 } |
174 | 190 |
175 /* Check STMT to detect whether a formal parameter is directly modified within | 191 /* Callback of walk_stmt_load_store_addr_ops for the visit_store and visit_addr |
176 STMT, the appropriate entry is updated in the modified flags of INFO. | 192 parameters. If OP is a parameter declaration, mark it as modified in the |
177 Directly means that this function does not check for modifications through | 193 info structure passed in DATA. */ |
178 pointers or escaping addresses because all TREE_ADDRESSABLE parameters are | 194 |
179 considered modified anyway. */ | 195 static bool |
180 | 196 visit_store_addr_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, |
181 static void | 197 tree op, void *data) |
182 ipa_check_stmt_modifications (struct ipa_node_params *info, gimple stmt) | 198 { |
183 { | 199 struct ipa_node_params *info = (struct ipa_node_params *) data; |
184 int j; | 200 |
185 int index; | 201 if (TREE_CODE (op) == PARM_DECL) |
186 tree lhs; | 202 { |
187 | 203 int index = ipa_get_param_decl_index (info, op); |
188 switch (gimple_code (stmt)) | 204 gcc_assert (index >= 0); |
189 { | 205 info->params[index].modified = true; |
190 case GIMPLE_ASSIGN: | 206 } |
191 lhs = gimple_assign_lhs (stmt); | 207 |
192 | 208 return false; |
193 while (handled_component_p (lhs)) | |
194 lhs = TREE_OPERAND (lhs, 0); | |
195 if (TREE_CODE (lhs) == SSA_NAME) | |
196 lhs = SSA_NAME_VAR (lhs); | |
197 index = ipa_get_param_decl_index (info, lhs); | |
198 if (index >= 0) | |
199 info->params[index].modified = true; | |
200 break; | |
201 | |
202 case GIMPLE_ASM: | |
203 /* Asm code could modify any of the parameters. */ | |
204 for (j = 0; j < ipa_get_param_count (info); j++) | |
205 info->params[j].modified = true; | |
206 break; | |
207 | |
208 default: | |
209 break; | |
210 } | |
211 } | 209 } |
212 | 210 |
213 /* Compute which formal parameters of function associated with NODE are locally | 211 /* Compute which formal parameters of function associated with NODE are locally |
214 modified. Parameters may be modified in NODE if they are TREE_ADDRESSABLE, | 212 modified or their address is taken. Note that this does not apply on |
215 if they appear on the left hand side of an assignment or if there is an | 213 parameters with SSA names but those can and should be analyzed |
216 ASM_EXPR in the function. */ | 214 differently. */ |
217 | 215 |
218 void | 216 void |
219 ipa_detect_param_modifications (struct cgraph_node *node) | 217 ipa_detect_param_modifications (struct cgraph_node *node) |
220 { | 218 { |
221 tree decl = node->decl; | 219 tree decl = node->decl; |
222 basic_block bb; | 220 basic_block bb; |
223 struct function *func; | 221 struct function *func; |
224 gimple_stmt_iterator gsi; | 222 gimple_stmt_iterator gsi; |
225 gimple stmt; | |
226 struct ipa_node_params *info = IPA_NODE_REF (node); | 223 struct ipa_node_params *info = IPA_NODE_REF (node); |
227 int i, count; | |
228 | 224 |
229 if (ipa_get_param_count (info) == 0 || info->modification_analysis_done) | 225 if (ipa_get_param_count (info) == 0 || info->modification_analysis_done) |
230 return; | 226 return; |
231 | 227 |
232 func = DECL_STRUCT_FUNCTION (decl); | 228 func = DECL_STRUCT_FUNCTION (decl); |
233 FOR_EACH_BB_FN (bb, func) | 229 FOR_EACH_BB_FN (bb, func) |
234 { | 230 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
235 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 231 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, NULL, |
236 { | 232 visit_store_addr_for_mod_analysis, |
237 stmt = gsi_stmt (gsi); | 233 visit_store_addr_for_mod_analysis); |
238 ipa_check_stmt_modifications (info, stmt); | |
239 } | |
240 } | |
241 | |
242 count = ipa_get_param_count (info); | |
243 for (i = 0; i < count; i++) | |
244 if (TREE_ADDRESSABLE (ipa_get_param (info, i))) | |
245 info->params[i].modified = true; | |
246 | 234 |
247 info->modification_analysis_done = 1; | 235 info->modification_analysis_done = 1; |
248 } | 236 } |
249 | 237 |
250 /* Count number of arguments callsite CS has and store it in | 238 /* Count number of arguments callsite CS has and store it in |
259 stmt = cs->call_stmt; | 247 stmt = cs->call_stmt; |
260 gcc_assert (is_gimple_call (stmt)); | 248 gcc_assert (is_gimple_call (stmt)); |
261 arg_num = gimple_call_num_args (stmt); | 249 arg_num = gimple_call_num_args (stmt); |
262 if (VEC_length (ipa_edge_args_t, ipa_edge_args_vector) | 250 if (VEC_length (ipa_edge_args_t, ipa_edge_args_vector) |
263 <= (unsigned) cgraph_edge_max_uid) | 251 <= (unsigned) cgraph_edge_max_uid) |
264 VEC_safe_grow_cleared (ipa_edge_args_t, heap, | 252 VEC_safe_grow_cleared (ipa_edge_args_t, gc, |
265 ipa_edge_args_vector, cgraph_edge_max_uid + 1); | 253 ipa_edge_args_vector, cgraph_edge_max_uid + 1); |
266 ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num); | 254 ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num); |
267 } | 255 } |
268 | 256 |
269 /* Print the jump functions of all arguments on all call graph edges going from | 257 /* Print the jump functions of all arguments on all call graph edges going from |
291 { | 279 { |
292 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | 280 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); |
293 type = jump_func->type; | 281 type = jump_func->type; |
294 | 282 |
295 fprintf (f, " param %d: ", i); | 283 fprintf (f, " param %d: ", i); |
296 if (type == IPA_UNKNOWN) | 284 if (type == IPA_JF_UNKNOWN) |
297 fprintf (f, "UNKNOWN\n"); | 285 fprintf (f, "UNKNOWN\n"); |
298 else if (type == IPA_CONST) | 286 else if (type == IPA_JF_CONST) |
299 { | 287 { |
300 tree val = jump_func->value.constant; | 288 tree val = jump_func->value.constant; |
301 fprintf (f, "CONST: "); | 289 fprintf (f, "CONST: "); |
302 print_generic_expr (f, val, 0); | 290 print_generic_expr (f, val, 0); |
303 fprintf (f, "\n"); | 291 fprintf (f, "\n"); |
304 } | 292 } |
305 else if (type == IPA_CONST_MEMBER_PTR) | 293 else if (type == IPA_JF_CONST_MEMBER_PTR) |
306 { | 294 { |
307 fprintf (f, "CONST MEMBER PTR: "); | 295 fprintf (f, "CONST MEMBER PTR: "); |
308 print_generic_expr (f, jump_func->value.member_cst.pfn, 0); | 296 print_generic_expr (f, jump_func->value.member_cst.pfn, 0); |
309 fprintf (f, ", "); | 297 fprintf (f, ", "); |
310 print_generic_expr (f, jump_func->value.member_cst.delta, 0); | 298 print_generic_expr (f, jump_func->value.member_cst.delta, 0); |
311 fprintf (f, "\n"); | 299 fprintf (f, "\n"); |
312 } | 300 } |
313 else if (type == IPA_PASS_THROUGH) | 301 else if (type == IPA_JF_PASS_THROUGH) |
314 { | 302 { |
315 fprintf (f, "PASS THROUGH: "); | 303 fprintf (f, "PASS THROUGH: "); |
316 fprintf (f, "%d\n", jump_func->value.formal_id); | 304 fprintf (f, "%d, op %s ", |
305 jump_func->value.pass_through.formal_id, | |
306 tree_code_name[(int) | |
307 jump_func->value.pass_through.operation]); | |
308 if (jump_func->value.pass_through.operation != NOP_EXPR) | |
309 print_generic_expr (dump_file, | |
310 jump_func->value.pass_through.operand, 0); | |
311 fprintf (dump_file, "\n"); | |
317 } | 312 } |
313 else if (type == IPA_JF_ANCESTOR) | |
314 { | |
315 fprintf (f, "ANCESTOR: "); | |
316 fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC"\n", | |
317 jump_func->value.ancestor.formal_id, | |
318 jump_func->value.ancestor.offset); | |
319 } | |
318 } | 320 } |
319 } | 321 } |
320 } | 322 } |
321 | 323 |
322 /* Print ipa_jump_func data structures of all nodes in the call graph to F. */ | 324 /* Print ipa_jump_func data structures of all nodes in the call graph to F. */ |
330 for (node = cgraph_nodes; node; node = node->next) | 332 for (node = cgraph_nodes; node; node = node->next) |
331 { | 333 { |
332 ipa_print_node_jump_functions (f, node); | 334 ipa_print_node_jump_functions (f, node); |
333 } | 335 } |
334 } | 336 } |
337 | |
338 /* Determine whether passing ssa name NAME constitutes a polynomial | |
339 pass-through function or getting an address of an acestor and if so, write | |
340 such a jump function to JFUNC. INFO describes the caller. */ | |
341 | |
342 static void | |
343 compute_complex_pass_through (struct ipa_node_params *info, | |
344 struct ipa_jump_func *jfunc, | |
345 tree name) | |
346 { | |
347 HOST_WIDE_INT offset, size, max_size; | |
348 tree op1, op2, type; | |
349 int index; | |
350 gimple stmt = SSA_NAME_DEF_STMT (name); | |
351 | |
352 if (!is_gimple_assign (stmt)) | |
353 return; | |
354 op1 = gimple_assign_rhs1 (stmt); | |
355 op2 = gimple_assign_rhs2 (stmt); | |
356 | |
357 if (op2) | |
358 { | |
359 if (TREE_CODE (op1) != SSA_NAME | |
360 || !SSA_NAME_IS_DEFAULT_DEF (op1) | |
361 || (TREE_CODE_CLASS (gimple_expr_code (stmt)) != tcc_comparison | |
362 && !useless_type_conversion_p (TREE_TYPE (name), | |
363 TREE_TYPE (op1))) | |
364 || !is_gimple_ip_invariant (op2)) | |
365 return; | |
366 | |
367 index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); | |
368 if (index >= 0) | |
369 { | |
370 jfunc->type = IPA_JF_PASS_THROUGH; | |
371 jfunc->value.pass_through.formal_id = index; | |
372 jfunc->value.pass_through.operation = gimple_assign_rhs_code (stmt); | |
373 jfunc->value.pass_through.operand = op2; | |
374 } | |
375 return; | |
376 } | |
377 | |
378 if (TREE_CODE (op1) != ADDR_EXPR) | |
379 return; | |
380 op1 = TREE_OPERAND (op1, 0); | |
381 type = TREE_TYPE (op1); | |
382 | |
383 op1 = get_ref_base_and_extent (op1, &offset, &size, &max_size); | |
384 if (TREE_CODE (op1) != INDIRECT_REF | |
385 /* If this is a varying address, punt. */ | |
386 || max_size == -1 | |
387 || max_size != size) | |
388 return; | |
389 op1 = TREE_OPERAND (op1, 0); | |
390 if (TREE_CODE (op1) != SSA_NAME | |
391 || !SSA_NAME_IS_DEFAULT_DEF (op1)) | |
392 return; | |
393 | |
394 index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); | |
395 if (index >= 0) | |
396 { | |
397 jfunc->type = IPA_JF_ANCESTOR; | |
398 jfunc->value.ancestor.formal_id = index; | |
399 jfunc->value.ancestor.offset = offset; | |
400 jfunc->value.ancestor.type = type; | |
401 } | |
402 } | |
403 | |
335 | 404 |
336 /* Determine the jump functions of scalar arguments. Scalar means SSA names | 405 /* Determine the jump functions of scalar arguments. Scalar means SSA names |
337 and constants of a number of selected types. INFO is the ipa_node_params | 406 and constants of a number of selected types. INFO is the ipa_node_params |
338 structure associated with the caller, FUNCTIONS is a pointer to an array of | 407 structure associated with the caller, FUNCTIONS is a pointer to an array of |
339 jump function structures associated with CALL which is the call statement | 408 jump function structures associated with CALL which is the call statement |
351 { | 420 { |
352 arg = gimple_call_arg (call, num); | 421 arg = gimple_call_arg (call, num); |
353 | 422 |
354 if (is_gimple_ip_invariant (arg)) | 423 if (is_gimple_ip_invariant (arg)) |
355 { | 424 { |
356 functions[num].type = IPA_CONST; | 425 functions[num].type = IPA_JF_CONST; |
357 functions[num].value.constant = arg; | 426 functions[num].value.constant = arg; |
358 } | 427 } |
359 else if ((TREE_CODE (arg) == SSA_NAME) && SSA_NAME_IS_DEFAULT_DEF (arg)) | 428 else if (TREE_CODE (arg) == SSA_NAME) |
360 { | 429 { |
361 int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg)); | 430 if (SSA_NAME_IS_DEFAULT_DEF (arg)) |
362 | |
363 if (index >= 0) | |
364 { | 431 { |
365 functions[num].type = IPA_PASS_THROUGH; | 432 int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg)); |
366 functions[num].value.formal_id = index; | 433 |
434 if (index >= 0) | |
435 { | |
436 functions[num].type = IPA_JF_PASS_THROUGH; | |
437 functions[num].value.pass_through.formal_id = index; | |
438 functions[num].value.pass_through.operation = NOP_EXPR; | |
439 } | |
367 } | 440 } |
441 else | |
442 compute_complex_pass_through (info, &functions[num], arg); | |
368 } | 443 } |
369 } | 444 } |
370 } | 445 } |
371 | 446 |
372 /* Inspect the given TYPE and return true iff it has the same structure (the | 447 /* Inspect the given TYPE and return true iff it has the same structure (the |
428 int index = ipa_get_param_decl_index (info, arg); | 503 int index = ipa_get_param_decl_index (info, arg); |
429 | 504 |
430 gcc_assert (index >=0); | 505 gcc_assert (index >=0); |
431 if (!ipa_is_param_modified (info, index)) | 506 if (!ipa_is_param_modified (info, index)) |
432 { | 507 { |
433 functions[num].type = IPA_PASS_THROUGH; | 508 functions[num].type = IPA_JF_PASS_THROUGH; |
434 functions[num].value.formal_id = index; | 509 functions[num].value.pass_through.formal_id = index; |
510 functions[num].value.pass_through.operation = NOP_EXPR; | |
435 } | 511 } |
436 else | 512 else |
437 undecided_members = true; | 513 undecided_members = true; |
438 } | 514 } |
439 else | 515 else |
449 | 525 |
450 static void | 526 static void |
451 fill_member_ptr_cst_jump_function (struct ipa_jump_func *jfunc, | 527 fill_member_ptr_cst_jump_function (struct ipa_jump_func *jfunc, |
452 tree pfn, tree delta) | 528 tree pfn, tree delta) |
453 { | 529 { |
454 jfunc->type = IPA_CONST_MEMBER_PTR; | 530 jfunc->type = IPA_JF_CONST_MEMBER_PTR; |
455 jfunc->value.member_cst.pfn = pfn; | 531 jfunc->value.member_cst.pfn = pfn; |
456 jfunc->value.member_cst.delta = delta; | 532 jfunc->value.member_cst.delta = delta; |
533 } | |
534 | |
535 /* If RHS is an SSA_NAMe and it is defined by a simple copy assign statement, | |
536 return the rhs of its defining statement. */ | |
537 | |
538 static inline tree | |
539 get_ssa_def_if_simple_copy (tree rhs) | |
540 { | |
541 while (TREE_CODE (rhs) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (rhs)) | |
542 { | |
543 gimple def_stmt = SSA_NAME_DEF_STMT (rhs); | |
544 | |
545 if (gimple_assign_single_p (def_stmt)) | |
546 rhs = gimple_assign_rhs1 (def_stmt); | |
547 else | |
548 break; | |
549 } | |
550 return rhs; | |
457 } | 551 } |
458 | 552 |
459 /* Traverse statements from CALL backwards, scanning whether the argument ARG | 553 /* Traverse statements from CALL backwards, scanning whether the argument ARG |
460 which is a member pointer is filled in with constant values. If it is, fill | 554 which is a member pointer is filled in with constant values. If it is, fill |
461 the jump function JFUNC in appropriately. METHOD_FIELD and DELTA_FIELD are | 555 the jump function JFUNC in appropriately. METHOD_FIELD and DELTA_FIELD are |
480 for (; !gsi_end_p (gsi); gsi_prev (&gsi)) | 574 for (; !gsi_end_p (gsi); gsi_prev (&gsi)) |
481 { | 575 { |
482 gimple stmt = gsi_stmt (gsi); | 576 gimple stmt = gsi_stmt (gsi); |
483 tree lhs, rhs, fld; | 577 tree lhs, rhs, fld; |
484 | 578 |
485 if (!is_gimple_assign (stmt) || gimple_num_ops (stmt) != 2) | 579 if (!gimple_assign_single_p (stmt)) |
486 return; | 580 return; |
487 | 581 |
488 lhs = gimple_assign_lhs (stmt); | 582 lhs = gimple_assign_lhs (stmt); |
489 rhs = gimple_assign_rhs1 (stmt); | 583 rhs = gimple_assign_rhs1 (stmt); |
490 | 584 |
493 continue; | 587 continue; |
494 | 588 |
495 fld = TREE_OPERAND (lhs, 1); | 589 fld = TREE_OPERAND (lhs, 1); |
496 if (!method && fld == method_field) | 590 if (!method && fld == method_field) |
497 { | 591 { |
592 rhs = get_ssa_def_if_simple_copy (rhs); | |
498 if (TREE_CODE (rhs) == ADDR_EXPR | 593 if (TREE_CODE (rhs) == ADDR_EXPR |
499 && TREE_CODE (TREE_OPERAND (rhs, 0)) == FUNCTION_DECL | 594 && TREE_CODE (TREE_OPERAND (rhs, 0)) == FUNCTION_DECL |
500 && TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) == METHOD_TYPE) | 595 && TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) == METHOD_TYPE) |
501 { | 596 { |
502 method = TREE_OPERAND (rhs, 0); | 597 method = TREE_OPERAND (rhs, 0); |
510 return; | 605 return; |
511 } | 606 } |
512 | 607 |
513 if (!delta && fld == delta_field) | 608 if (!delta && fld == delta_field) |
514 { | 609 { |
610 rhs = get_ssa_def_if_simple_copy (rhs); | |
515 if (TREE_CODE (rhs) == INTEGER_CST) | 611 if (TREE_CODE (rhs) == INTEGER_CST) |
516 { | 612 { |
517 delta = rhs; | 613 delta = rhs; |
518 if (method) | 614 if (method) |
519 { | 615 { |
543 | 639 |
544 for (num = 0; num < gimple_call_num_args (call); num++) | 640 for (num = 0; num < gimple_call_num_args (call); num++) |
545 { | 641 { |
546 arg = gimple_call_arg (call, num); | 642 arg = gimple_call_arg (call, num); |
547 | 643 |
548 if (functions[num].type == IPA_UNKNOWN | 644 if (functions[num].type == IPA_JF_UNKNOWN |
549 && type_like_member_ptr_p (TREE_TYPE (arg), &method_field, | 645 && type_like_member_ptr_p (TREE_TYPE (arg), &method_field, |
550 &delta_field)) | 646 &delta_field)) |
551 determine_cst_member_ptr (call, arg, method_field, delta_field, | 647 determine_cst_member_ptr (call, arg, method_field, delta_field, |
552 &functions[num]); | 648 &functions[num]); |
553 } | 649 } |
564 struct ipa_edge_args *arguments = IPA_EDGE_REF (cs); | 660 struct ipa_edge_args *arguments = IPA_EDGE_REF (cs); |
565 gimple call; | 661 gimple call; |
566 | 662 |
567 if (ipa_get_cs_argument_count (arguments) == 0 || arguments->jump_functions) | 663 if (ipa_get_cs_argument_count (arguments) == 0 || arguments->jump_functions) |
568 return; | 664 return; |
569 arguments->jump_functions = XCNEWVEC (struct ipa_jump_func, | 665 arguments->jump_functions = GGC_CNEWVEC (struct ipa_jump_func, |
570 ipa_get_cs_argument_count (arguments)); | 666 ipa_get_cs_argument_count (arguments)); |
571 | 667 |
572 call = cs->call_stmt; | 668 call = cs->call_stmt; |
573 gcc_assert (is_gimple_call (call)); | 669 gcc_assert (is_gimple_call (call)); |
574 | 670 |
575 /* We will deal with constants and SSA scalars first: */ | 671 /* We will deal with constants and SSA scalars first: */ |
583 /* Finally, let's check whether we actually pass a new constant member | 679 /* Finally, let's check whether we actually pass a new constant member |
584 pointer here... */ | 680 pointer here... */ |
585 compute_cst_member_ptr_arguments (arguments->jump_functions, call); | 681 compute_cst_member_ptr_arguments (arguments->jump_functions, call); |
586 } | 682 } |
587 | 683 |
588 /* If RHS looks like a rhs of a statement loading pfn from a member pointer | 684 /* If RHS looks like a rhs of a statement loading pfn from a member |
589 formal parameter, return the parameter, otherwise return NULL. */ | 685 pointer formal parameter, return the parameter, otherwise return |
686 NULL. If USE_DELTA, then we look for a use of the delta field | |
687 rather than the pfn. */ | |
590 | 688 |
591 static tree | 689 static tree |
592 ipa_get_member_ptr_load_param (tree rhs) | 690 ipa_get_member_ptr_load_param (tree rhs, bool use_delta) |
593 { | 691 { |
594 tree rec, fld; | 692 tree rec, fld; |
595 tree ptr_field; | 693 tree ptr_field; |
694 tree delta_field; | |
596 | 695 |
597 if (TREE_CODE (rhs) != COMPONENT_REF) | 696 if (TREE_CODE (rhs) != COMPONENT_REF) |
598 return NULL_TREE; | 697 return NULL_TREE; |
599 | 698 |
600 rec = TREE_OPERAND (rhs, 0); | 699 rec = TREE_OPERAND (rhs, 0); |
601 if (TREE_CODE (rec) != PARM_DECL | 700 if (TREE_CODE (rec) != PARM_DECL |
602 || !type_like_member_ptr_p (TREE_TYPE (rec), &ptr_field, NULL)) | 701 || !type_like_member_ptr_p (TREE_TYPE (rec), &ptr_field, &delta_field)) |
603 return NULL_TREE; | 702 return NULL_TREE; |
604 | 703 |
605 fld = TREE_OPERAND (rhs, 1); | 704 fld = TREE_OPERAND (rhs, 1); |
606 if (fld == ptr_field) | 705 if (use_delta ? (fld == delta_field) : (fld == ptr_field)) |
607 return rec; | 706 return rec; |
608 else | 707 else |
609 return NULL_TREE; | 708 return NULL_TREE; |
610 } | 709 } |
611 | 710 |
612 /* If STMT looks like a statement loading a value from a member pointer formal | 711 /* If STMT looks like a statement loading a value from a member pointer formal |
613 parameter, this function returns that parameter. */ | 712 parameter, this function returns that parameter. */ |
614 | 713 |
615 static tree | 714 static tree |
616 ipa_get_stmt_member_ptr_load_param (gimple stmt) | 715 ipa_get_stmt_member_ptr_load_param (gimple stmt, bool use_delta) |
617 { | 716 { |
618 tree rhs; | 717 tree rhs; |
619 | 718 |
620 if (!is_gimple_assign (stmt) || gimple_num_ops (stmt) != 2) | 719 if (!gimple_assign_single_p (stmt)) |
621 return NULL_TREE; | 720 return NULL_TREE; |
622 | 721 |
623 rhs = gimple_assign_rhs1 (stmt); | 722 rhs = gimple_assign_rhs1 (stmt); |
624 return ipa_get_member_ptr_load_param (rhs); | 723 return ipa_get_member_ptr_load_param (rhs, use_delta); |
625 } | 724 } |
626 | 725 |
627 /* Returns true iff T is an SSA_NAME defined by a statement. */ | 726 /* Returns true iff T is an SSA_NAME defined by a statement. */ |
628 | 727 |
629 static bool | 728 static bool |
650 info->params[formal_id].called = 1; | 749 info->params[formal_id].called = 1; |
651 | 750 |
652 note = XCNEW (struct ipa_param_call_note); | 751 note = XCNEW (struct ipa_param_call_note); |
653 note->formal_id = formal_id; | 752 note->formal_id = formal_id; |
654 note->stmt = stmt; | 753 note->stmt = stmt; |
754 note->lto_stmt_uid = gimple_uid (stmt); | |
655 note->count = bb->count; | 755 note->count = bb->count; |
656 note->frequency = compute_call_stmt_bb_frequency (bb); | 756 note->frequency = compute_call_stmt_bb_frequency (current_function_decl, bb); |
757 note->loop_nest = bb->loop_depth; | |
657 | 758 |
658 note->next = info->param_calls; | 759 note->next = info->param_calls; |
659 info->param_calls = note; | 760 info->param_calls = note; |
660 | 761 |
661 return; | 762 return; |
754 if (!ipa_is_ssa_with_stmt_def (n1) || !ipa_is_ssa_with_stmt_def (n2)) | 855 if (!ipa_is_ssa_with_stmt_def (n1) || !ipa_is_ssa_with_stmt_def (n2)) |
755 return; | 856 return; |
756 d1 = SSA_NAME_DEF_STMT (n1); | 857 d1 = SSA_NAME_DEF_STMT (n1); |
757 d2 = SSA_NAME_DEF_STMT (n2); | 858 d2 = SSA_NAME_DEF_STMT (n2); |
758 | 859 |
759 if ((rec = ipa_get_stmt_member_ptr_load_param (d1))) | 860 if ((rec = ipa_get_stmt_member_ptr_load_param (d1, false))) |
760 { | 861 { |
761 if (ipa_get_stmt_member_ptr_load_param (d2)) | 862 if (ipa_get_stmt_member_ptr_load_param (d2, false)) |
762 return; | 863 return; |
763 | 864 |
764 bb = gimple_bb (d1); | 865 bb = gimple_bb (d1); |
765 virt_bb = gimple_bb (d2); | 866 virt_bb = gimple_bb (d2); |
766 } | 867 } |
767 else if ((rec = ipa_get_stmt_member_ptr_load_param (d2))) | 868 else if ((rec = ipa_get_stmt_member_ptr_load_param (d2, false))) |
768 { | 869 { |
769 bb = gimple_bb (d2); | 870 bb = gimple_bb (d2); |
770 virt_bb = gimple_bb (d1); | 871 virt_bb = gimple_bb (d1); |
771 } | 872 } |
772 else | 873 else |
795 cond = gimple_cond_lhs (branch); | 896 cond = gimple_cond_lhs (branch); |
796 if (!ipa_is_ssa_with_stmt_def (cond)) | 897 if (!ipa_is_ssa_with_stmt_def (cond)) |
797 return; | 898 return; |
798 | 899 |
799 def = SSA_NAME_DEF_STMT (cond); | 900 def = SSA_NAME_DEF_STMT (cond); |
800 if (!is_gimple_assign (def) || gimple_num_ops (def) != 3 | 901 if (!is_gimple_assign (def) |
801 || gimple_assign_rhs_code (def) != BIT_AND_EXPR | 902 || gimple_assign_rhs_code (def) != BIT_AND_EXPR |
802 || !integer_onep (gimple_assign_rhs2 (def))) | 903 || !integer_onep (gimple_assign_rhs2 (def))) |
803 return; | 904 return; |
804 | 905 |
805 cond = gimple_assign_rhs1 (def); | 906 cond = gimple_assign_rhs1 (def); |
806 if (!ipa_is_ssa_with_stmt_def (cond)) | 907 if (!ipa_is_ssa_with_stmt_def (cond)) |
807 return; | 908 return; |
808 | 909 |
809 def = SSA_NAME_DEF_STMT (cond); | 910 def = SSA_NAME_DEF_STMT (cond); |
810 | 911 |
811 if (is_gimple_assign (def) && gimple_num_ops (def) == 2 | 912 if (is_gimple_assign (def) |
812 && gimple_assign_rhs_code (def) == NOP_EXPR) | 913 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))) |
813 { | 914 { |
814 cond = gimple_assign_rhs1 (def); | 915 cond = gimple_assign_rhs1 (def); |
815 if (!ipa_is_ssa_with_stmt_def (cond)) | 916 if (!ipa_is_ssa_with_stmt_def (cond)) |
816 return; | 917 return; |
817 def = SSA_NAME_DEF_STMT (cond); | 918 def = SSA_NAME_DEF_STMT (cond); |
818 } | 919 } |
819 | 920 |
820 rec2 = ipa_get_stmt_member_ptr_load_param (def); | 921 rec2 = ipa_get_stmt_member_ptr_load_param (def, |
922 (TARGET_PTRMEMFUNC_VBIT_LOCATION | |
923 == ptrmemfunc_vbit_in_delta)); | |
924 | |
821 if (rec != rec2) | 925 if (rec != rec2) |
822 return; | 926 return; |
823 | 927 |
824 index = ipa_get_param_decl_index (info, rec); | 928 index = ipa_get_param_decl_index (info, rec); |
825 if (index >= 0 && !ipa_is_param_modified (info, index)) | 929 if (index >= 0 && !ipa_is_param_modified (info, index)) |
868 info->uses_analysis_done = 1; | 972 info->uses_analysis_done = 1; |
869 } | 973 } |
870 | 974 |
871 /* Update the jump functions associated with call graph edge E when the call | 975 /* Update the jump functions associated with call graph edge E when the call |
872 graph edge CS is being inlined, assuming that E->caller is already (possibly | 976 graph edge CS is being inlined, assuming that E->caller is already (possibly |
873 indirectly) inlined into CS->callee and that E has not been inlined. */ | 977 indirectly) inlined into CS->callee and that E has not been inlined. |
978 | |
979 We keep pass through functions only if they do not contain any operation. | |
980 This is sufficient for inlining and greately simplifies things. */ | |
874 | 981 |
875 static void | 982 static void |
876 update_jump_functions_after_inlining (struct cgraph_edge *cs, | 983 update_jump_functions_after_inlining (struct cgraph_edge *cs, |
877 struct cgraph_edge *e) | 984 struct cgraph_edge *e) |
878 { | 985 { |
883 | 990 |
884 for (i = 0; i < count; i++) | 991 for (i = 0; i < count; i++) |
885 { | 992 { |
886 struct ipa_jump_func *src, *dst = ipa_get_ith_jump_func (args, i); | 993 struct ipa_jump_func *src, *dst = ipa_get_ith_jump_func (args, i); |
887 | 994 |
888 if (dst->type != IPA_PASS_THROUGH) | 995 if (dst->type == IPA_JF_ANCESTOR) |
996 { | |
997 dst->type = IPA_JF_UNKNOWN; | |
998 continue; | |
999 } | |
1000 | |
1001 if (dst->type != IPA_JF_PASS_THROUGH) | |
889 continue; | 1002 continue; |
890 | 1003 |
891 /* We must check range due to calls with variable number of arguments: */ | 1004 /* We must check range due to calls with variable number of arguments and |
892 if (dst->value.formal_id >= (unsigned) ipa_get_cs_argument_count (top)) | 1005 we cannot combine jump functions with operations. */ |
893 { | 1006 if (dst->value.pass_through.operation != NOP_EXPR |
894 dst->type = IPA_BOTTOM; | 1007 || (dst->value.pass_through.formal_id |
1008 >= ipa_get_cs_argument_count (top))) | |
1009 { | |
1010 dst->type = IPA_JF_UNKNOWN; | |
895 continue; | 1011 continue; |
896 } | 1012 } |
897 | 1013 |
898 src = ipa_get_ith_jump_func (top, dst->value.formal_id); | 1014 src = ipa_get_ith_jump_func (top, dst->value.pass_through.formal_id); |
899 *dst = *src; | 1015 *dst = *src; |
900 } | 1016 } |
901 } | 1017 } |
902 | 1018 |
903 /* Print out a debug message to file F that we have discovered that an indirect | 1019 /* Print out a debug message to file F that we have discovered that an indirect |
908 print_edge_addition_message (FILE *f, struct ipa_param_call_note *nt, | 1024 print_edge_addition_message (FILE *f, struct ipa_param_call_note *nt, |
909 struct ipa_jump_func *jfunc, | 1025 struct ipa_jump_func *jfunc, |
910 struct cgraph_node *node) | 1026 struct cgraph_node *node) |
911 { | 1027 { |
912 fprintf (f, "ipa-prop: Discovered an indirect call to a known target ("); | 1028 fprintf (f, "ipa-prop: Discovered an indirect call to a known target ("); |
913 if (jfunc->type == IPA_CONST_MEMBER_PTR) | 1029 if (jfunc->type == IPA_JF_CONST_MEMBER_PTR) |
914 { | 1030 { |
915 print_node_brief (f, "", jfunc->value.member_cst.pfn, 0); | 1031 print_node_brief (f, "", jfunc->value.member_cst.pfn, 0); |
916 print_node_brief (f, ", ", jfunc->value.member_cst.delta, 0); | 1032 print_node_brief (f, ", ", jfunc->value.member_cst.delta, 0); |
917 } | 1033 } |
918 else | 1034 else |
944 | 1060 |
945 if (nt->processed) | 1061 if (nt->processed) |
946 continue; | 1062 continue; |
947 | 1063 |
948 /* We must check range due to calls with variable number of arguments: */ | 1064 /* We must check range due to calls with variable number of arguments: */ |
949 if (nt->formal_id >= (unsigned) ipa_get_cs_argument_count (top)) | 1065 if (nt->formal_id >= ipa_get_cs_argument_count (top)) |
950 { | 1066 { |
951 nt->processed = true; | 1067 nt->processed = true; |
952 continue; | 1068 continue; |
953 } | 1069 } |
954 | 1070 |
955 jfunc = ipa_get_ith_jump_func (top, nt->formal_id); | 1071 jfunc = ipa_get_ith_jump_func (top, nt->formal_id); |
956 if (jfunc->type == IPA_PASS_THROUGH) | 1072 if (jfunc->type == IPA_JF_PASS_THROUGH |
957 nt->formal_id = jfunc->value.formal_id; | 1073 && jfunc->value.pass_through.operation == NOP_EXPR) |
958 else if (jfunc->type == IPA_CONST || jfunc->type == IPA_CONST_MEMBER_PTR) | 1074 nt->formal_id = jfunc->value.pass_through.formal_id; |
1075 else if (jfunc->type == IPA_JF_CONST | |
1076 || jfunc->type == IPA_JF_CONST_MEMBER_PTR) | |
959 { | 1077 { |
960 struct cgraph_node *callee; | 1078 struct cgraph_node *callee; |
961 struct cgraph_edge *new_indirect_edge; | 1079 struct cgraph_edge *new_indirect_edge; |
962 tree decl; | 1080 tree decl; |
963 | 1081 |
964 nt->processed = true; | 1082 nt->processed = true; |
965 if (jfunc->type == IPA_CONST_MEMBER_PTR) | 1083 if (jfunc->type == IPA_JF_CONST_MEMBER_PTR) |
966 decl = jfunc->value.member_cst.pfn; | 1084 decl = jfunc->value.member_cst.pfn; |
967 else | 1085 else |
968 decl = jfunc->value.constant; | 1086 decl = jfunc->value.constant; |
969 | 1087 |
970 if (TREE_CODE (decl) != ADDR_EXPR) | 1088 if (TREE_CODE (decl) != ADDR_EXPR) |
982 print_edge_addition_message (dump_file, nt, jfunc, node); | 1100 print_edge_addition_message (dump_file, nt, jfunc, node); |
983 | 1101 |
984 new_indirect_edge = cgraph_create_edge (node, callee, nt->stmt, | 1102 new_indirect_edge = cgraph_create_edge (node, callee, nt->stmt, |
985 nt->count, nt->frequency, | 1103 nt->count, nt->frequency, |
986 nt->loop_nest); | 1104 nt->loop_nest); |
1105 new_indirect_edge->lto_stmt_uid = nt->lto_stmt_uid; | |
987 new_indirect_edge->indirect_call = 1; | 1106 new_indirect_edge->indirect_call = 1; |
988 ipa_check_create_edge_args (); | 1107 ipa_check_create_edge_args (); |
989 if (new_edges) | 1108 if (new_edges) |
990 VEC_safe_push (cgraph_edge_p, heap, *new_edges, new_indirect_edge); | 1109 VEC_safe_push (cgraph_edge_p, heap, *new_edges, new_indirect_edge); |
991 top = IPA_EDGE_REF (cs); | 1110 top = IPA_EDGE_REF (cs); |
1111 } | |
1112 else | |
1113 { | |
1114 /* Ancestor jum functions and pass theoughs with operations should | |
1115 not be used on parameters that then get called. */ | |
1116 gcc_assert (jfunc->type == IPA_JF_UNKNOWN); | |
1117 nt->processed = true; | |
992 } | 1118 } |
993 } | 1119 } |
994 return res; | 1120 return res; |
995 } | 1121 } |
996 | 1122 |
1029 | 1155 |
1030 bool | 1156 bool |
1031 ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, | 1157 ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, |
1032 VEC (cgraph_edge_p, heap) **new_edges) | 1158 VEC (cgraph_edge_p, heap) **new_edges) |
1033 { | 1159 { |
1160 /* FIXME lto: We do not stream out indirect call information. */ | |
1161 if (flag_wpa) | |
1162 return false; | |
1163 | |
1034 /* Do nothing if the preparation phase has not been carried out yet | 1164 /* Do nothing if the preparation phase has not been carried out yet |
1035 (i.e. during early inlining). */ | 1165 (i.e. during early inlining). */ |
1036 if (!ipa_node_params_vector) | 1166 if (!ipa_node_params_vector) |
1037 return false; | 1167 return false; |
1038 gcc_assert (ipa_edge_args_vector); | 1168 gcc_assert (ipa_edge_args_vector); |
1045 | 1175 |
1046 void | 1176 void |
1047 ipa_free_edge_args_substructures (struct ipa_edge_args *args) | 1177 ipa_free_edge_args_substructures (struct ipa_edge_args *args) |
1048 { | 1178 { |
1049 if (args->jump_functions) | 1179 if (args->jump_functions) |
1050 free (args->jump_functions); | 1180 ggc_free (args->jump_functions); |
1051 | 1181 |
1052 memset (args, 0, sizeof (*args)); | 1182 memset (args, 0, sizeof (*args)); |
1053 } | 1183 } |
1054 | 1184 |
1055 /* Free all ipa_edge structures. */ | 1185 /* Free all ipa_edge structures. */ |
1063 for (i = 0; | 1193 for (i = 0; |
1064 VEC_iterate (ipa_edge_args_t, ipa_edge_args_vector, i, args); | 1194 VEC_iterate (ipa_edge_args_t, ipa_edge_args_vector, i, args); |
1065 i++) | 1195 i++) |
1066 ipa_free_edge_args_substructures (args); | 1196 ipa_free_edge_args_substructures (args); |
1067 | 1197 |
1068 VEC_free (ipa_edge_args_t, heap, ipa_edge_args_vector); | 1198 VEC_free (ipa_edge_args_t, gc, ipa_edge_args_vector); |
1069 ipa_edge_args_vector = NULL; | 1199 ipa_edge_args_vector = NULL; |
1070 } | 1200 } |
1071 | 1201 |
1072 /* Frees all dynamically allocated structures that the param info points | 1202 /* Frees all dynamically allocated structures that the param info points |
1073 to. */ | 1203 to. */ |
1134 void *p; | 1264 void *p; |
1135 | 1265 |
1136 if (!src) | 1266 if (!src) |
1137 return NULL; | 1267 return NULL; |
1138 | 1268 |
1139 p = xcalloc (1, n); | 1269 p = xmalloc (n); |
1270 memcpy (p, src, n); | |
1271 return p; | |
1272 } | |
1273 | |
1274 /* Like duplicate_array byt in GGC memory. */ | |
1275 | |
1276 static void * | |
1277 duplicate_ggc_array (void *src, size_t n) | |
1278 { | |
1279 void *p; | |
1280 | |
1281 if (!src) | |
1282 return NULL; | |
1283 | |
1284 p = ggc_alloc (n); | |
1140 memcpy (p, src, n); | 1285 memcpy (p, src, n); |
1141 return p; | 1286 return p; |
1142 } | 1287 } |
1143 | 1288 |
1144 /* Hook that is called by cgraph.c when a node is duplicated. */ | 1289 /* Hook that is called by cgraph.c when a node is duplicated. */ |
1156 new_args = IPA_EDGE_REF (dst); | 1301 new_args = IPA_EDGE_REF (dst); |
1157 | 1302 |
1158 arg_count = ipa_get_cs_argument_count (old_args); | 1303 arg_count = ipa_get_cs_argument_count (old_args); |
1159 ipa_set_cs_argument_count (new_args, arg_count); | 1304 ipa_set_cs_argument_count (new_args, arg_count); |
1160 new_args->jump_functions = (struct ipa_jump_func *) | 1305 new_args->jump_functions = (struct ipa_jump_func *) |
1161 duplicate_array (old_args->jump_functions, | 1306 duplicate_ggc_array (old_args->jump_functions, |
1162 sizeof (struct ipa_jump_func) * arg_count); | 1307 sizeof (struct ipa_jump_func) * arg_count); |
1163 } | 1308 } |
1164 | 1309 |
1165 /* Hook that is called by cgraph.c when a node is duplicated. */ | 1310 /* Hook that is called by cgraph.c when a node is duplicated. */ |
1166 | 1311 |
1167 static void | 1312 static void |
1273 for (i = 0; i < count; i++) | 1418 for (i = 0; i < count; i++) |
1274 { | 1419 { |
1275 temp = ipa_get_param (info, i); | 1420 temp = ipa_get_param (info, i); |
1276 if (TREE_CODE (temp) == PARM_DECL) | 1421 if (TREE_CODE (temp) == PARM_DECL) |
1277 fprintf (f, " param %d : %s", i, | 1422 fprintf (f, " param %d : %s", i, |
1278 (*lang_hooks.decl_printable_name) (temp, 2)); | 1423 (DECL_NAME (temp) |
1424 ? (*lang_hooks.decl_printable_name) (temp, 2) | |
1425 : "(unnamed)")); | |
1279 if (ipa_is_param_modified (info, i)) | 1426 if (ipa_is_param_modified (info, i)) |
1280 fprintf (f, " modified"); | 1427 fprintf (f, " modified"); |
1281 if (ipa_is_param_called (info, i)) | 1428 if (ipa_is_param_called (info, i)) |
1282 fprintf (f, " called"); | 1429 fprintf (f, " called"); |
1283 fprintf (f, "\n"); | 1430 fprintf (f, "\n"); |
1294 | 1441 |
1295 fprintf (f, "\nFunction parameters:\n"); | 1442 fprintf (f, "\nFunction parameters:\n"); |
1296 for (node = cgraph_nodes; node; node = node->next) | 1443 for (node = cgraph_nodes; node; node = node->next) |
1297 ipa_print_node_params (f, node); | 1444 ipa_print_node_params (f, node); |
1298 } | 1445 } |
1446 | |
1447 /* Return a heap allocated vector containing formal parameters of FNDECL. */ | |
1448 | |
1449 VEC(tree, heap) * | |
1450 ipa_get_vector_of_formal_parms (tree fndecl) | |
1451 { | |
1452 VEC(tree, heap) *args; | |
1453 int count; | |
1454 tree parm; | |
1455 | |
1456 count = count_formal_params_1 (fndecl); | |
1457 args = VEC_alloc (tree, heap, count); | |
1458 for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) | |
1459 VEC_quick_push (tree, args, parm); | |
1460 | |
1461 return args; | |
1462 } | |
1463 | |
1464 /* Return a heap allocated vector containing types of formal parameters of | |
1465 function type FNTYPE. */ | |
1466 | |
1467 static inline VEC(tree, heap) * | |
1468 get_vector_of_formal_parm_types (tree fntype) | |
1469 { | |
1470 VEC(tree, heap) *types; | |
1471 int count = 0; | |
1472 tree t; | |
1473 | |
1474 for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t)) | |
1475 count++; | |
1476 | |
1477 types = VEC_alloc (tree, heap, count); | |
1478 for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t)) | |
1479 VEC_quick_push (tree, types, TREE_VALUE (t)); | |
1480 | |
1481 return types; | |
1482 } | |
1483 | |
1484 /* Modify the function declaration FNDECL and its type according to the plan in | |
1485 ADJUSTMENTS. It also sets base fields of individual adjustments structures | |
1486 to reflect the actual parameters being modified which are determined by the | |
1487 base_index field. */ | |
1488 | |
1489 void | |
1490 ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, | |
1491 const char *synth_parm_prefix) | |
1492 { | |
1493 VEC(tree, heap) *oparms, *otypes; | |
1494 tree orig_type, new_type = NULL; | |
1495 tree old_arg_types, t, new_arg_types = NULL; | |
1496 tree parm, *link = &DECL_ARGUMENTS (fndecl); | |
1497 int i, len = VEC_length (ipa_parm_adjustment_t, adjustments); | |
1498 tree new_reversed = NULL; | |
1499 bool care_for_types, last_parm_void; | |
1500 | |
1501 if (!synth_parm_prefix) | |
1502 synth_parm_prefix = "SYNTH"; | |
1503 | |
1504 oparms = ipa_get_vector_of_formal_parms (fndecl); | |
1505 orig_type = TREE_TYPE (fndecl); | |
1506 old_arg_types = TYPE_ARG_TYPES (orig_type); | |
1507 | |
1508 /* The following test is an ugly hack, some functions simply don't have any | |
1509 arguments in their type. This is probably a bug but well... */ | |
1510 care_for_types = (old_arg_types != NULL_TREE); | |
1511 if (care_for_types) | |
1512 { | |
1513 last_parm_void = (TREE_VALUE (tree_last (old_arg_types)) | |
1514 == void_type_node); | |
1515 otypes = get_vector_of_formal_parm_types (orig_type); | |
1516 if (last_parm_void) | |
1517 gcc_assert (VEC_length (tree, oparms) + 1 == VEC_length (tree, otypes)); | |
1518 else | |
1519 gcc_assert (VEC_length (tree, oparms) == VEC_length (tree, otypes)); | |
1520 } | |
1521 else | |
1522 { | |
1523 last_parm_void = false; | |
1524 otypes = NULL; | |
1525 } | |
1526 | |
1527 for (i = 0; i < len; i++) | |
1528 { | |
1529 struct ipa_parm_adjustment *adj; | |
1530 gcc_assert (link); | |
1531 | |
1532 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i); | |
1533 parm = VEC_index (tree, oparms, adj->base_index); | |
1534 adj->base = parm; | |
1535 | |
1536 if (adj->copy_param) | |
1537 { | |
1538 if (care_for_types) | |
1539 new_arg_types = tree_cons (NULL_TREE, VEC_index (tree, otypes, | |
1540 adj->base_index), | |
1541 new_arg_types); | |
1542 *link = parm; | |
1543 link = &TREE_CHAIN (parm); | |
1544 } | |
1545 else if (!adj->remove_param) | |
1546 { | |
1547 tree new_parm; | |
1548 tree ptype; | |
1549 | |
1550 if (adj->by_ref) | |
1551 ptype = build_pointer_type (adj->type); | |
1552 else | |
1553 ptype = adj->type; | |
1554 | |
1555 if (care_for_types) | |
1556 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types); | |
1557 | |
1558 new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, | |
1559 ptype); | |
1560 DECL_NAME (new_parm) = create_tmp_var_name (synth_parm_prefix); | |
1561 | |
1562 DECL_ARTIFICIAL (new_parm) = 1; | |
1563 DECL_ARG_TYPE (new_parm) = ptype; | |
1564 DECL_CONTEXT (new_parm) = fndecl; | |
1565 TREE_USED (new_parm) = 1; | |
1566 DECL_IGNORED_P (new_parm) = 1; | |
1567 layout_decl (new_parm, 0); | |
1568 | |
1569 add_referenced_var (new_parm); | |
1570 mark_sym_for_renaming (new_parm); | |
1571 adj->base = parm; | |
1572 adj->reduction = new_parm; | |
1573 | |
1574 *link = new_parm; | |
1575 | |
1576 link = &TREE_CHAIN (new_parm); | |
1577 } | |
1578 } | |
1579 | |
1580 *link = NULL_TREE; | |
1581 | |
1582 if (care_for_types) | |
1583 { | |
1584 new_reversed = nreverse (new_arg_types); | |
1585 if (last_parm_void) | |
1586 { | |
1587 if (new_reversed) | |
1588 TREE_CHAIN (new_arg_types) = void_list_node; | |
1589 else | |
1590 new_reversed = void_list_node; | |
1591 } | |
1592 } | |
1593 | |
1594 /* Use copy_node to preserve as much as possible from original type | |
1595 (debug info, attribute lists etc.) | |
1596 Exception is METHOD_TYPEs must have THIS argument. | |
1597 When we are asked to remove it, we need to build new FUNCTION_TYPE | |
1598 instead. */ | |
1599 if (TREE_CODE (orig_type) != METHOD_TYPE | |
1600 || (VEC_index (ipa_parm_adjustment_t, adjustments, 0)->copy_param | |
1601 && VEC_index (ipa_parm_adjustment_t, adjustments, 0)->base_index == 0)) | |
1602 { | |
1603 new_type = copy_node (orig_type); | |
1604 TYPE_ARG_TYPES (new_type) = new_reversed; | |
1605 } | |
1606 else | |
1607 { | |
1608 new_type | |
1609 = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type), | |
1610 new_reversed)); | |
1611 TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type); | |
1612 DECL_VINDEX (fndecl) = NULL_TREE; | |
1613 } | |
1614 | |
1615 /* This is a new type, not a copy of an old type. Need to reassociate | |
1616 variants. We can handle everything except the main variant lazily. */ | |
1617 t = TYPE_MAIN_VARIANT (orig_type); | |
1618 if (orig_type != t) | |
1619 { | |
1620 TYPE_MAIN_VARIANT (new_type) = t; | |
1621 TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t); | |
1622 TYPE_NEXT_VARIANT (t) = new_type; | |
1623 } | |
1624 else | |
1625 { | |
1626 TYPE_MAIN_VARIANT (new_type) = new_type; | |
1627 TYPE_NEXT_VARIANT (new_type) = NULL; | |
1628 } | |
1629 | |
1630 TREE_TYPE (fndecl) = new_type; | |
1631 if (otypes) | |
1632 VEC_free (tree, heap, otypes); | |
1633 VEC_free (tree, heap, oparms); | |
1634 } | |
1635 | |
1636 /* Modify actual arguments of a function call CS as indicated in ADJUSTMENTS. | |
1637 If this is a directly recursive call, CS must be NULL. Otherwise it must | |
1638 contain the corresponding call graph edge. */ | |
1639 | |
1640 void | |
1641 ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, | |
1642 ipa_parm_adjustment_vec adjustments) | |
1643 { | |
1644 VEC(tree, heap) *vargs; | |
1645 gimple new_stmt; | |
1646 gimple_stmt_iterator gsi; | |
1647 tree callee_decl; | |
1648 int i, len; | |
1649 | |
1650 len = VEC_length (ipa_parm_adjustment_t, adjustments); | |
1651 vargs = VEC_alloc (tree, heap, len); | |
1652 | |
1653 gsi = gsi_for_stmt (stmt); | |
1654 for (i = 0; i < len; i++) | |
1655 { | |
1656 struct ipa_parm_adjustment *adj; | |
1657 | |
1658 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i); | |
1659 | |
1660 if (adj->copy_param) | |
1661 { | |
1662 tree arg = gimple_call_arg (stmt, adj->base_index); | |
1663 | |
1664 VEC_quick_push (tree, vargs, arg); | |
1665 } | |
1666 else if (!adj->remove_param) | |
1667 { | |
1668 tree expr, orig_expr; | |
1669 bool allow_ptr, repl_found; | |
1670 | |
1671 orig_expr = expr = gimple_call_arg (stmt, adj->base_index); | |
1672 if (TREE_CODE (expr) == ADDR_EXPR) | |
1673 { | |
1674 allow_ptr = false; | |
1675 expr = TREE_OPERAND (expr, 0); | |
1676 } | |
1677 else | |
1678 allow_ptr = true; | |
1679 | |
1680 repl_found = build_ref_for_offset (&expr, TREE_TYPE (expr), | |
1681 adj->offset, adj->type, | |
1682 allow_ptr); | |
1683 if (repl_found) | |
1684 { | |
1685 if (adj->by_ref) | |
1686 expr = build_fold_addr_expr (expr); | |
1687 } | |
1688 else | |
1689 { | |
1690 tree ptrtype = build_pointer_type (adj->type); | |
1691 expr = orig_expr; | |
1692 if (!POINTER_TYPE_P (TREE_TYPE (expr))) | |
1693 expr = build_fold_addr_expr (expr); | |
1694 if (!useless_type_conversion_p (ptrtype, TREE_TYPE (expr))) | |
1695 expr = fold_convert (ptrtype, expr); | |
1696 expr = fold_build2 (POINTER_PLUS_EXPR, ptrtype, expr, | |
1697 build_int_cst (size_type_node, | |
1698 adj->offset / BITS_PER_UNIT)); | |
1699 if (!adj->by_ref) | |
1700 expr = fold_build1 (INDIRECT_REF, adj->type, expr); | |
1701 } | |
1702 expr = force_gimple_operand_gsi (&gsi, expr, | |
1703 adj->by_ref | |
1704 || is_gimple_reg_type (adj->type), | |
1705 NULL, true, GSI_SAME_STMT); | |
1706 VEC_quick_push (tree, vargs, expr); | |
1707 } | |
1708 } | |
1709 | |
1710 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1711 { | |
1712 fprintf (dump_file, "replacing stmt:"); | |
1713 print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, 0); | |
1714 } | |
1715 | |
1716 callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl; | |
1717 new_stmt = gimple_build_call_vec (callee_decl, vargs); | |
1718 VEC_free (tree, heap, vargs); | |
1719 if (gimple_call_lhs (stmt)) | |
1720 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); | |
1721 | |
1722 gimple_set_block (new_stmt, gimple_block (stmt)); | |
1723 if (gimple_has_location (stmt)) | |
1724 gimple_set_location (new_stmt, gimple_location (stmt)); | |
1725 gimple_call_copy_flags (new_stmt, stmt); | |
1726 gimple_call_set_chain (new_stmt, gimple_call_chain (stmt)); | |
1727 | |
1728 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1729 { | |
1730 fprintf (dump_file, "with stmt:"); | |
1731 print_gimple_stmt (dump_file, new_stmt, 0, 0); | |
1732 fprintf (dump_file, "\n"); | |
1733 } | |
1734 gsi_replace (&gsi, new_stmt, true); | |
1735 if (cs) | |
1736 cgraph_set_call_stmt (cs, new_stmt); | |
1737 update_ssa (TODO_update_ssa); | |
1738 free_dominance_info (CDI_DOMINATORS); | |
1739 } | |
1740 | |
1741 /* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */ | |
1742 | |
1743 static bool | |
1744 index_in_adjustments_multiple_times_p (int base_index, | |
1745 ipa_parm_adjustment_vec adjustments) | |
1746 { | |
1747 int i, len = VEC_length (ipa_parm_adjustment_t, adjustments); | |
1748 bool one = false; | |
1749 | |
1750 for (i = 0; i < len; i++) | |
1751 { | |
1752 struct ipa_parm_adjustment *adj; | |
1753 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i); | |
1754 | |
1755 if (adj->base_index == base_index) | |
1756 { | |
1757 if (one) | |
1758 return true; | |
1759 else | |
1760 one = true; | |
1761 } | |
1762 } | |
1763 return false; | |
1764 } | |
1765 | |
1766 | |
1767 /* Return adjustments that should have the same effect on function parameters | |
1768 and call arguments as if they were first changed according to adjustments in | |
1769 INNER and then by adjustments in OUTER. */ | |
1770 | |
1771 ipa_parm_adjustment_vec | |
1772 ipa_combine_adjustments (ipa_parm_adjustment_vec inner, | |
1773 ipa_parm_adjustment_vec outer) | |
1774 { | |
1775 int i, outlen = VEC_length (ipa_parm_adjustment_t, outer); | |
1776 int inlen = VEC_length (ipa_parm_adjustment_t, inner); | |
1777 int removals = 0; | |
1778 ipa_parm_adjustment_vec adjustments, tmp; | |
1779 | |
1780 tmp = VEC_alloc (ipa_parm_adjustment_t, heap, inlen); | |
1781 for (i = 0; i < inlen; i++) | |
1782 { | |
1783 struct ipa_parm_adjustment *n; | |
1784 n = VEC_index (ipa_parm_adjustment_t, inner, i); | |
1785 | |
1786 if (n->remove_param) | |
1787 removals++; | |
1788 else | |
1789 VEC_quick_push (ipa_parm_adjustment_t, tmp, n); | |
1790 } | |
1791 | |
1792 adjustments = VEC_alloc (ipa_parm_adjustment_t, heap, outlen + removals); | |
1793 for (i = 0; i < outlen; i++) | |
1794 { | |
1795 struct ipa_parm_adjustment *r; | |
1796 struct ipa_parm_adjustment *out = VEC_index (ipa_parm_adjustment_t, | |
1797 outer, i); | |
1798 struct ipa_parm_adjustment *in = VEC_index (ipa_parm_adjustment_t, tmp, | |
1799 out->base_index); | |
1800 | |
1801 gcc_assert (!in->remove_param); | |
1802 if (out->remove_param) | |
1803 { | |
1804 if (!index_in_adjustments_multiple_times_p (in->base_index, tmp)) | |
1805 { | |
1806 r = VEC_quick_push (ipa_parm_adjustment_t, adjustments, NULL); | |
1807 memset (r, 0, sizeof (*r)); | |
1808 r->remove_param = true; | |
1809 } | |
1810 continue; | |
1811 } | |
1812 | |
1813 r = VEC_quick_push (ipa_parm_adjustment_t, adjustments, NULL); | |
1814 memset (r, 0, sizeof (*r)); | |
1815 r->base_index = in->base_index; | |
1816 r->type = out->type; | |
1817 | |
1818 /* FIXME: Create nonlocal value too. */ | |
1819 | |
1820 if (in->copy_param && out->copy_param) | |
1821 r->copy_param = true; | |
1822 else if (in->copy_param) | |
1823 r->offset = out->offset; | |
1824 else if (out->copy_param) | |
1825 r->offset = in->offset; | |
1826 else | |
1827 r->offset = in->offset + out->offset; | |
1828 } | |
1829 | |
1830 for (i = 0; i < inlen; i++) | |
1831 { | |
1832 struct ipa_parm_adjustment *n = VEC_index (ipa_parm_adjustment_t, | |
1833 inner, i); | |
1834 | |
1835 if (n->remove_param) | |
1836 VEC_quick_push (ipa_parm_adjustment_t, adjustments, n); | |
1837 } | |
1838 | |
1839 VEC_free (ipa_parm_adjustment_t, heap, tmp); | |
1840 return adjustments; | |
1841 } | |
1842 | |
1843 /* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human | |
1844 friendly way, assuming they are meant to be applied to FNDECL. */ | |
1845 | |
1846 void | |
1847 ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments, | |
1848 tree fndecl) | |
1849 { | |
1850 int i, len = VEC_length (ipa_parm_adjustment_t, adjustments); | |
1851 bool first = true; | |
1852 VEC(tree, heap) *parms = ipa_get_vector_of_formal_parms (fndecl); | |
1853 | |
1854 fprintf (file, "IPA param adjustments: "); | |
1855 for (i = 0; i < len; i++) | |
1856 { | |
1857 struct ipa_parm_adjustment *adj; | |
1858 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i); | |
1859 | |
1860 if (!first) | |
1861 fprintf (file, " "); | |
1862 else | |
1863 first = false; | |
1864 | |
1865 fprintf (file, "%i. base_index: %i - ", i, adj->base_index); | |
1866 print_generic_expr (file, VEC_index (tree, parms, adj->base_index), 0); | |
1867 if (adj->base) | |
1868 { | |
1869 fprintf (file, ", base: "); | |
1870 print_generic_expr (file, adj->base, 0); | |
1871 } | |
1872 if (adj->reduction) | |
1873 { | |
1874 fprintf (file, ", reduction: "); | |
1875 print_generic_expr (file, adj->reduction, 0); | |
1876 } | |
1877 if (adj->new_ssa_base) | |
1878 { | |
1879 fprintf (file, ", new_ssa_base: "); | |
1880 print_generic_expr (file, adj->new_ssa_base, 0); | |
1881 } | |
1882 | |
1883 if (adj->copy_param) | |
1884 fprintf (file, ", copy_param"); | |
1885 else if (adj->remove_param) | |
1886 fprintf (file, ", remove_param"); | |
1887 else | |
1888 fprintf (file, ", offset %li", (long) adj->offset); | |
1889 if (adj->by_ref) | |
1890 fprintf (file, ", by_ref"); | |
1891 print_node_brief (file, ", type: ", adj->type, 0); | |
1892 fprintf (file, "\n"); | |
1893 } | |
1894 VEC_free (tree, heap, parms); | |
1895 } | |
1896 | |
1897 /* Stream out jump function JUMP_FUNC to OB. */ | |
1898 | |
1899 static void | |
1900 ipa_write_jump_function (struct output_block *ob, | |
1901 struct ipa_jump_func *jump_func) | |
1902 { | |
1903 lto_output_uleb128_stream (ob->main_stream, | |
1904 jump_func->type); | |
1905 | |
1906 switch (jump_func->type) | |
1907 { | |
1908 case IPA_JF_UNKNOWN: | |
1909 break; | |
1910 case IPA_JF_CONST: | |
1911 lto_output_tree (ob, jump_func->value.constant, true); | |
1912 break; | |
1913 case IPA_JF_PASS_THROUGH: | |
1914 lto_output_tree (ob, jump_func->value.pass_through.operand, true); | |
1915 lto_output_uleb128_stream (ob->main_stream, | |
1916 jump_func->value.pass_through.formal_id); | |
1917 lto_output_uleb128_stream (ob->main_stream, | |
1918 jump_func->value.pass_through.operation); | |
1919 break; | |
1920 case IPA_JF_ANCESTOR: | |
1921 lto_output_uleb128_stream (ob->main_stream, | |
1922 jump_func->value.ancestor.offset); | |
1923 lto_output_tree (ob, jump_func->value.ancestor.type, true); | |
1924 lto_output_uleb128_stream (ob->main_stream, | |
1925 jump_func->value.ancestor.formal_id); | |
1926 break; | |
1927 case IPA_JF_CONST_MEMBER_PTR: | |
1928 lto_output_tree (ob, jump_func->value.member_cst.pfn, true); | |
1929 lto_output_tree (ob, jump_func->value.member_cst.delta, false); | |
1930 break; | |
1931 } | |
1932 } | |
1933 | |
1934 /* Read in jump function JUMP_FUNC from IB. */ | |
1935 | |
1936 static void | |
1937 ipa_read_jump_function (struct lto_input_block *ib, | |
1938 struct ipa_jump_func *jump_func, | |
1939 struct data_in *data_in) | |
1940 { | |
1941 jump_func->type = (enum jump_func_type) lto_input_uleb128 (ib); | |
1942 | |
1943 switch (jump_func->type) | |
1944 { | |
1945 case IPA_JF_UNKNOWN: | |
1946 break; | |
1947 case IPA_JF_CONST: | |
1948 jump_func->value.constant = lto_input_tree (ib, data_in); | |
1949 break; | |
1950 case IPA_JF_PASS_THROUGH: | |
1951 jump_func->value.pass_through.operand = lto_input_tree (ib, data_in); | |
1952 jump_func->value.pass_through.formal_id = lto_input_uleb128 (ib); | |
1953 jump_func->value.pass_through.operation = (enum tree_code) lto_input_uleb128 (ib); | |
1954 break; | |
1955 case IPA_JF_ANCESTOR: | |
1956 jump_func->value.ancestor.offset = lto_input_uleb128 (ib); | |
1957 jump_func->value.ancestor.type = lto_input_tree (ib, data_in); | |
1958 jump_func->value.ancestor.formal_id = lto_input_uleb128 (ib); | |
1959 break; | |
1960 case IPA_JF_CONST_MEMBER_PTR: | |
1961 jump_func->value.member_cst.pfn = lto_input_tree (ib, data_in); | |
1962 jump_func->value.member_cst.delta = lto_input_tree (ib, data_in); | |
1963 break; | |
1964 } | |
1965 } | |
1966 | |
1967 /* Stream out a parameter call note. */ | |
1968 | |
1969 static void | |
1970 ipa_write_param_call_note (struct output_block *ob, | |
1971 struct ipa_param_call_note *note) | |
1972 { | |
1973 gcc_assert (!note->processed); | |
1974 lto_output_uleb128_stream (ob->main_stream, gimple_uid (note->stmt)); | |
1975 lto_output_sleb128_stream (ob->main_stream, note->formal_id); | |
1976 lto_output_sleb128_stream (ob->main_stream, note->count); | |
1977 lto_output_sleb128_stream (ob->main_stream, note->frequency); | |
1978 lto_output_sleb128_stream (ob->main_stream, note->loop_nest); | |
1979 } | |
1980 | |
1981 /* Read in a parameter call note. */ | |
1982 | |
1983 static void | |
1984 ipa_read_param_call_note (struct lto_input_block *ib, | |
1985 struct ipa_node_params *info) | |
1986 | |
1987 { | |
1988 struct ipa_param_call_note *note = XCNEW (struct ipa_param_call_note); | |
1989 | |
1990 note->lto_stmt_uid = (unsigned int) lto_input_uleb128 (ib); | |
1991 note->formal_id = (int) lto_input_sleb128 (ib); | |
1992 note->count = (gcov_type) lto_input_sleb128 (ib); | |
1993 note->frequency = (int) lto_input_sleb128 (ib); | |
1994 note->loop_nest = (int) lto_input_sleb128 (ib); | |
1995 | |
1996 note->next = info->param_calls; | |
1997 info->param_calls = note; | |
1998 } | |
1999 | |
2000 | |
2001 /* Stream out NODE info to OB. */ | |
2002 | |
2003 static void | |
2004 ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) | |
2005 { | |
2006 int node_ref; | |
2007 lto_cgraph_encoder_t encoder; | |
2008 struct ipa_node_params *info = IPA_NODE_REF (node); | |
2009 int j; | |
2010 struct cgraph_edge *e; | |
2011 struct bitpack_d *bp; | |
2012 int note_count = 0; | |
2013 struct ipa_param_call_note *note; | |
2014 | |
2015 encoder = ob->decl_state->cgraph_node_encoder; | |
2016 node_ref = lto_cgraph_encoder_encode (encoder, node); | |
2017 lto_output_uleb128_stream (ob->main_stream, node_ref); | |
2018 | |
2019 bp = bitpack_create (); | |
2020 bp_pack_value (bp, info->called_with_var_arguments, 1); | |
2021 gcc_assert (info->modification_analysis_done | |
2022 || ipa_get_param_count (info) == 0); | |
2023 gcc_assert (info->uses_analysis_done || ipa_get_param_count (info) == 0); | |
2024 gcc_assert (!info->node_enqueued); | |
2025 gcc_assert (!info->ipcp_orig_node); | |
2026 for (j = 0; j < ipa_get_param_count (info); j++) | |
2027 { | |
2028 bp_pack_value (bp, info->params[j].modified, 1); | |
2029 bp_pack_value (bp, info->params[j].called, 1); | |
2030 } | |
2031 lto_output_bitpack (ob->main_stream, bp); | |
2032 bitpack_delete (bp); | |
2033 for (e = node->callees; e; e = e->next_callee) | |
2034 { | |
2035 struct ipa_edge_args *args = IPA_EDGE_REF (e); | |
2036 | |
2037 lto_output_uleb128_stream (ob->main_stream, | |
2038 ipa_get_cs_argument_count (args)); | |
2039 for (j = 0; j < ipa_get_cs_argument_count (args); j++) | |
2040 ipa_write_jump_function (ob, ipa_get_ith_jump_func (args, j)); | |
2041 } | |
2042 | |
2043 for (note = info->param_calls; note; note = note->next) | |
2044 note_count++; | |
2045 lto_output_uleb128_stream (ob->main_stream, note_count); | |
2046 for (note = info->param_calls; note; note = note->next) | |
2047 ipa_write_param_call_note (ob, note); | |
2048 } | |
2049 | |
2050 /* Srtream in NODE info from IB. */ | |
2051 | |
2052 static void | |
2053 ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, | |
2054 struct data_in *data_in) | |
2055 { | |
2056 struct ipa_node_params *info = IPA_NODE_REF (node); | |
2057 int k; | |
2058 struct cgraph_edge *e; | |
2059 struct bitpack_d *bp; | |
2060 int i, note_count; | |
2061 | |
2062 ipa_initialize_node_params (node); | |
2063 | |
2064 bp = lto_input_bitpack (ib); | |
2065 info->called_with_var_arguments = bp_unpack_value (bp, 1); | |
2066 if (ipa_get_param_count (info) != 0) | |
2067 { | |
2068 info->modification_analysis_done = true; | |
2069 info->uses_analysis_done = true; | |
2070 } | |
2071 info->node_enqueued = false; | |
2072 for (k = 0; k < ipa_get_param_count (info); k++) | |
2073 { | |
2074 info->params[k].modified = bp_unpack_value (bp, 1); | |
2075 info->params[k].called = bp_unpack_value (bp, 1); | |
2076 } | |
2077 bitpack_delete (bp); | |
2078 for (e = node->callees; e; e = e->next_callee) | |
2079 { | |
2080 struct ipa_edge_args *args = IPA_EDGE_REF (e); | |
2081 int count = lto_input_uleb128 (ib); | |
2082 | |
2083 ipa_set_cs_argument_count (args, count); | |
2084 if (!count) | |
2085 continue; | |
2086 | |
2087 args->jump_functions = GGC_CNEWVEC (struct ipa_jump_func, | |
2088 ipa_get_cs_argument_count (args)); | |
2089 for (k = 0; k < ipa_get_cs_argument_count (args); k++) | |
2090 ipa_read_jump_function (ib, ipa_get_ith_jump_func (args, k), data_in); | |
2091 } | |
2092 | |
2093 note_count = lto_input_uleb128 (ib); | |
2094 for (i = 0; i < note_count; i++) | |
2095 ipa_read_param_call_note (ib, info); | |
2096 } | |
2097 | |
2098 /* Write jump functions for nodes in SET. */ | |
2099 | |
2100 void | |
2101 ipa_prop_write_jump_functions (cgraph_node_set set) | |
2102 { | |
2103 struct cgraph_node *node; | |
2104 struct output_block *ob = create_output_block (LTO_section_jump_functions); | |
2105 unsigned int count = 0; | |
2106 cgraph_node_set_iterator csi; | |
2107 | |
2108 ob->cgraph_node = NULL; | |
2109 | |
2110 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | |
2111 { | |
2112 node = csi_node (csi); | |
2113 if (node->analyzed && IPA_NODE_REF (node) != NULL) | |
2114 count++; | |
2115 } | |
2116 | |
2117 lto_output_uleb128_stream (ob->main_stream, count); | |
2118 | |
2119 /* Process all of the functions. */ | |
2120 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | |
2121 { | |
2122 node = csi_node (csi); | |
2123 if (node->analyzed && IPA_NODE_REF (node) != NULL) | |
2124 ipa_write_node_info (ob, node); | |
2125 } | |
2126 lto_output_1_stream (ob->main_stream, 0); | |
2127 produce_asm (ob, NULL); | |
2128 destroy_output_block (ob); | |
2129 } | |
2130 | |
2131 /* Read section in file FILE_DATA of length LEN with data DATA. */ | |
2132 | |
2133 static void | |
2134 ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data, | |
2135 size_t len) | |
2136 { | |
2137 const struct lto_function_header *header = | |
2138 (const struct lto_function_header *) data; | |
2139 const int32_t cfg_offset = sizeof (struct lto_function_header); | |
2140 const int32_t main_offset = cfg_offset + header->cfg_size; | |
2141 const int32_t string_offset = main_offset + header->main_size; | |
2142 struct data_in *data_in; | |
2143 struct lto_input_block ib_main; | |
2144 unsigned int i; | |
2145 unsigned int count; | |
2146 | |
2147 LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0, | |
2148 header->main_size); | |
2149 | |
2150 data_in = | |
2151 lto_data_in_create (file_data, (const char *) data + string_offset, | |
2152 header->string_size, NULL); | |
2153 count = lto_input_uleb128 (&ib_main); | |
2154 | |
2155 for (i = 0; i < count; i++) | |
2156 { | |
2157 unsigned int index; | |
2158 struct cgraph_node *node; | |
2159 lto_cgraph_encoder_t encoder; | |
2160 | |
2161 index = lto_input_uleb128 (&ib_main); | |
2162 encoder = file_data->cgraph_node_encoder; | |
2163 node = lto_cgraph_encoder_deref (encoder, index); | |
2164 ipa_read_node_info (&ib_main, node, data_in); | |
2165 } | |
2166 lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, | |
2167 len); | |
2168 lto_data_in_delete (data_in); | |
2169 } | |
2170 | |
2171 /* Read ipcp jump functions. */ | |
2172 | |
2173 void | |
2174 ipa_prop_read_jump_functions (void) | |
2175 { | |
2176 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data (); | |
2177 struct lto_file_decl_data *file_data; | |
2178 unsigned int j = 0; | |
2179 | |
2180 ipa_check_create_node_params (); | |
2181 ipa_check_create_edge_args (); | |
2182 ipa_register_cgraph_hooks (); | |
2183 | |
2184 while ((file_data = file_data_vec[j++])) | |
2185 { | |
2186 size_t len; | |
2187 const char *data = lto_get_section_data (file_data, LTO_section_jump_functions, NULL, &len); | |
2188 | |
2189 if (data) | |
2190 ipa_prop_read_section (file_data, data, len); | |
2191 } | |
2192 } | |
2193 | |
2194 /* After merging units, we can get mismatch in argument counts. | |
2195 Also decl merging might've rendered parameter lists obsolette. | |
2196 Also compute called_with_variable_arg info. */ | |
2197 | |
2198 void | |
2199 ipa_update_after_lto_read (void) | |
2200 { | |
2201 struct cgraph_node *node; | |
2202 struct cgraph_edge *cs; | |
2203 | |
2204 ipa_check_create_node_params (); | |
2205 ipa_check_create_edge_args (); | |
2206 | |
2207 for (node = cgraph_nodes; node; node = node->next) | |
2208 { | |
2209 if (!node->analyzed) | |
2210 continue; | |
2211 ipa_initialize_node_params (node); | |
2212 for (cs = node->callees; cs; cs = cs->next_callee) | |
2213 { | |
2214 if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) | |
2215 != ipa_get_param_count (IPA_NODE_REF (cs->callee))) | |
2216 ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee)); | |
2217 } | |
2218 } | |
2219 } | |
2220 | |
2221 /* Walk param call notes of NODE and set their call statements given the uid | |
2222 stored in each note and STMTS which is an array of statements indexed by the | |
2223 uid. */ | |
2224 | |
2225 void | |
2226 lto_ipa_fixup_call_notes (struct cgraph_node *node, gimple *stmts) | |
2227 { | |
2228 struct ipa_node_params *info; | |
2229 struct ipa_param_call_note *note; | |
2230 | |
2231 ipa_check_create_node_params (); | |
2232 info = IPA_NODE_REF (node); | |
2233 note = info->param_calls; | |
2234 /* If there are no notes or they have already been fixed up (the same fixup | |
2235 is called for both inlining and ipa-cp), there's nothing to do. */ | |
2236 if (!note || note->stmt) | |
2237 return; | |
2238 | |
2239 do | |
2240 { | |
2241 note->stmt = stmts[note->lto_stmt_uid]; | |
2242 note = note->next; | |
2243 } | |
2244 while (note); | |
2245 } |