Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-prop.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Interprocedural analyses. | 1 /* Interprocedural analyses. |
2 Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc. | 2 Copyright (C) 2005, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | |
3 | 4 |
4 This file is part of GCC. | 5 This file is part of GCC. |
5 | 6 |
6 GCC is free software; you can redistribute it and/or modify it under | 7 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 | 8 the terms of the GNU General Public License as published by the Free |
27 #include "cgraph.h" | 28 #include "cgraph.h" |
28 #include "ipa-prop.h" | 29 #include "ipa-prop.h" |
29 #include "tree-flow.h" | 30 #include "tree-flow.h" |
30 #include "tree-pass.h" | 31 #include "tree-pass.h" |
31 #include "tree-inline.h" | 32 #include "tree-inline.h" |
33 #include "gimple.h" | |
32 #include "flags.h" | 34 #include "flags.h" |
33 #include "timevar.h" | 35 #include "timevar.h" |
34 #include "flags.h" | 36 #include "flags.h" |
35 #include "diagnostic.h" | 37 #include "diagnostic.h" |
38 #include "tree-pretty-print.h" | |
39 #include "gimple-pretty-print.h" | |
36 #include "lto-streamer.h" | 40 #include "lto-streamer.h" |
37 | 41 |
38 /* Vector where the parameter infos are actually stored. */ | 42 /* Vector where the parameter infos are actually stored. */ |
39 VEC (ipa_node_params_t, heap) *ipa_node_params_vector; | 43 VEC (ipa_node_params_t, heap) *ipa_node_params_vector; |
40 /* Vector where the parameter infos are actually stored. */ | 44 /* Vector where the parameter infos are actually stored. */ |
41 VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector; | 45 VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector; |
46 | |
47 /* Bitmap with all UIDs of call graph edges that have been already processed | |
48 by indirect inlining. */ | |
49 static bitmap iinlining_processed_edges; | |
42 | 50 |
43 /* Holders of ipa cgraph hooks: */ | 51 /* Holders of ipa cgraph hooks: */ |
44 static struct cgraph_edge_hook_list *edge_removal_hook_holder; | 52 static struct cgraph_edge_hook_list *edge_removal_hook_holder; |
45 static struct cgraph_node_hook_list *node_removal_hook_holder; | 53 static struct cgraph_node_hook_list *node_removal_hook_holder; |
46 static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; | 54 static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; |
196 visit_store_addr_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, | 204 visit_store_addr_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, |
197 tree op, void *data) | 205 tree op, void *data) |
198 { | 206 { |
199 struct ipa_node_params *info = (struct ipa_node_params *) data; | 207 struct ipa_node_params *info = (struct ipa_node_params *) data; |
200 | 208 |
201 if (TREE_CODE (op) == PARM_DECL) | 209 op = get_base_address (op); |
210 if (op | |
211 && TREE_CODE (op) == PARM_DECL) | |
202 { | 212 { |
203 int index = ipa_get_param_decl_index (info, op); | 213 int index = ipa_get_param_decl_index (info, op); |
204 gcc_assert (index >= 0); | 214 gcc_assert (index >= 0); |
205 info->params[index].modified = true; | 215 info->params[index].modified = true; |
216 info->params[index].used = true; | |
217 } | |
218 | |
219 return false; | |
220 } | |
221 | |
222 /* Callback of walk_stmt_load_store_addr_ops for the visit_load. | |
223 If OP is a parameter declaration, mark it as used in the info structure | |
224 passed in DATA. */ | |
225 | |
226 static bool | |
227 visit_load_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, | |
228 tree op, void *data) | |
229 { | |
230 struct ipa_node_params *info = (struct ipa_node_params *) data; | |
231 | |
232 op = get_base_address (op); | |
233 if (op | |
234 && TREE_CODE (op) == PARM_DECL) | |
235 { | |
236 int index = ipa_get_param_decl_index (info, op); | |
237 gcc_assert (index >= 0); | |
238 info->params[index].used = true; | |
206 } | 239 } |
207 | 240 |
208 return false; | 241 return false; |
209 } | 242 } |
210 | 243 |
219 tree decl = node->decl; | 252 tree decl = node->decl; |
220 basic_block bb; | 253 basic_block bb; |
221 struct function *func; | 254 struct function *func; |
222 gimple_stmt_iterator gsi; | 255 gimple_stmt_iterator gsi; |
223 struct ipa_node_params *info = IPA_NODE_REF (node); | 256 struct ipa_node_params *info = IPA_NODE_REF (node); |
257 int i; | |
224 | 258 |
225 if (ipa_get_param_count (info) == 0 || info->modification_analysis_done) | 259 if (ipa_get_param_count (info) == 0 || info->modification_analysis_done) |
226 return; | 260 return; |
261 | |
262 for (i = 0; i < ipa_get_param_count (info); i++) | |
263 { | |
264 tree parm = ipa_get_param (info, i); | |
265 /* For SSA regs see if parameter is used. For non-SSA we compute | |
266 the flag during modification analysis. */ | |
267 if (is_gimple_reg (parm) | |
268 && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm)) | |
269 info->params[i].used = true; | |
270 } | |
227 | 271 |
228 func = DECL_STRUCT_FUNCTION (decl); | 272 func = DECL_STRUCT_FUNCTION (decl); |
229 FOR_EACH_BB_FN (bb, func) | 273 FOR_EACH_BB_FN (bb, func) |
230 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 274 { |
231 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, NULL, | 275 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
232 visit_store_addr_for_mod_analysis, | 276 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, |
233 visit_store_addr_for_mod_analysis); | 277 visit_load_for_mod_analysis, |
278 visit_store_addr_for_mod_analysis, | |
279 visit_store_addr_for_mod_analysis); | |
280 for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) | |
281 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, | |
282 visit_load_for_mod_analysis, | |
283 visit_store_addr_for_mod_analysis, | |
284 visit_store_addr_for_mod_analysis); | |
285 } | |
234 | 286 |
235 info->modification_analysis_done = 1; | 287 info->modification_analysis_done = 1; |
236 } | 288 } |
237 | 289 |
238 /* Count number of arguments callsite CS has and store it in | 290 /* Count number of arguments callsite CS has and store it in |
252 VEC_safe_grow_cleared (ipa_edge_args_t, gc, | 304 VEC_safe_grow_cleared (ipa_edge_args_t, gc, |
253 ipa_edge_args_vector, cgraph_edge_max_uid + 1); | 305 ipa_edge_args_vector, cgraph_edge_max_uid + 1); |
254 ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num); | 306 ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num); |
255 } | 307 } |
256 | 308 |
309 /* Print the jump functions associated with call graph edge CS to file F. */ | |
310 | |
311 static void | |
312 ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) | |
313 { | |
314 int i, count; | |
315 | |
316 count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); | |
317 for (i = 0; i < count; i++) | |
318 { | |
319 struct ipa_jump_func *jump_func; | |
320 enum jump_func_type type; | |
321 | |
322 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | |
323 type = jump_func->type; | |
324 | |
325 fprintf (f, " param %d: ", i); | |
326 if (type == IPA_JF_UNKNOWN) | |
327 fprintf (f, "UNKNOWN\n"); | |
328 else if (type == IPA_JF_KNOWN_TYPE) | |
329 { | |
330 tree binfo_type = TREE_TYPE (jump_func->value.base_binfo); | |
331 fprintf (f, "KNOWN TYPE, type in binfo is: "); | |
332 print_generic_expr (f, binfo_type, 0); | |
333 fprintf (f, " (%u)\n", TYPE_UID (binfo_type)); | |
334 } | |
335 else if (type == IPA_JF_CONST) | |
336 { | |
337 tree val = jump_func->value.constant; | |
338 fprintf (f, "CONST: "); | |
339 print_generic_expr (f, val, 0); | |
340 if (TREE_CODE (val) == ADDR_EXPR | |
341 && TREE_CODE (TREE_OPERAND (val, 0)) == CONST_DECL) | |
342 { | |
343 fprintf (f, " -> "); | |
344 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (val, 0)), | |
345 0); | |
346 } | |
347 fprintf (f, "\n"); | |
348 } | |
349 else if (type == IPA_JF_CONST_MEMBER_PTR) | |
350 { | |
351 fprintf (f, "CONST MEMBER PTR: "); | |
352 print_generic_expr (f, jump_func->value.member_cst.pfn, 0); | |
353 fprintf (f, ", "); | |
354 print_generic_expr (f, jump_func->value.member_cst.delta, 0); | |
355 fprintf (f, "\n"); | |
356 } | |
357 else if (type == IPA_JF_PASS_THROUGH) | |
358 { | |
359 fprintf (f, "PASS THROUGH: "); | |
360 fprintf (f, "%d, op %s ", | |
361 jump_func->value.pass_through.formal_id, | |
362 tree_code_name[(int) | |
363 jump_func->value.pass_through.operation]); | |
364 if (jump_func->value.pass_through.operation != NOP_EXPR) | |
365 print_generic_expr (dump_file, | |
366 jump_func->value.pass_through.operand, 0); | |
367 fprintf (dump_file, "\n"); | |
368 } | |
369 else if (type == IPA_JF_ANCESTOR) | |
370 { | |
371 fprintf (f, "ANCESTOR: "); | |
372 fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC", ", | |
373 jump_func->value.ancestor.formal_id, | |
374 jump_func->value.ancestor.offset); | |
375 print_generic_expr (f, jump_func->value.ancestor.type, 0); | |
376 fprintf (dump_file, "\n"); | |
377 } | |
378 } | |
379 } | |
380 | |
381 | |
257 /* Print the jump functions of all arguments on all call graph edges going from | 382 /* Print the jump functions of all arguments on all call graph edges going from |
258 NODE to file F. */ | 383 NODE to file F. */ |
259 | 384 |
260 void | 385 void |
261 ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) | 386 ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) |
262 { | 387 { |
263 int i, count; | |
264 struct cgraph_edge *cs; | 388 struct cgraph_edge *cs; |
265 struct ipa_jump_func *jump_func; | 389 int i; |
266 enum jump_func_type type; | |
267 | 390 |
268 fprintf (f, " Jump functions of caller %s:\n", cgraph_node_name (node)); | 391 fprintf (f, " Jump functions of caller %s:\n", cgraph_node_name (node)); |
269 for (cs = node->callees; cs; cs = cs->next_callee) | 392 for (cs = node->callees; cs; cs = cs->next_callee) |
270 { | 393 { |
271 if (!ipa_edge_args_info_available_for_edge_p (cs)) | 394 if (!ipa_edge_args_info_available_for_edge_p (cs)) |
272 continue; | 395 continue; |
273 | 396 |
274 fprintf (f, " callsite %s ", cgraph_node_name (node)); | 397 fprintf (f, " callsite %s/%i -> %s/%i : \n", |
275 fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); | 398 cgraph_node_name (node), node->uid, |
276 | 399 cgraph_node_name (cs->callee), cs->callee->uid); |
277 count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); | 400 ipa_print_node_jump_functions_for_edge (f, cs); |
278 for (i = 0; i < count; i++) | 401 } |
279 { | 402 |
280 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | 403 for (cs = node->indirect_calls, i = 0; cs; cs = cs->next_callee, i++) |
281 type = jump_func->type; | 404 { |
282 | 405 if (!ipa_edge_args_info_available_for_edge_p (cs)) |
283 fprintf (f, " param %d: ", i); | 406 continue; |
284 if (type == IPA_JF_UNKNOWN) | 407 |
285 fprintf (f, "UNKNOWN\n"); | 408 if (cs->call_stmt) |
286 else if (type == IPA_JF_CONST) | 409 { |
287 { | 410 fprintf (f, " indirect callsite %d for stmt ", i); |
288 tree val = jump_func->value.constant; | 411 print_gimple_stmt (f, cs->call_stmt, 0, TDF_SLIM); |
289 fprintf (f, "CONST: "); | 412 } |
290 print_generic_expr (f, val, 0); | 413 else |
291 fprintf (f, "\n"); | 414 fprintf (f, " indirect callsite %d :\n", i); |
292 } | 415 ipa_print_node_jump_functions_for_edge (f, cs); |
293 else if (type == IPA_JF_CONST_MEMBER_PTR) | 416 |
294 { | |
295 fprintf (f, "CONST MEMBER PTR: "); | |
296 print_generic_expr (f, jump_func->value.member_cst.pfn, 0); | |
297 fprintf (f, ", "); | |
298 print_generic_expr (f, jump_func->value.member_cst.delta, 0); | |
299 fprintf (f, "\n"); | |
300 } | |
301 else if (type == IPA_JF_PASS_THROUGH) | |
302 { | |
303 fprintf (f, "PASS THROUGH: "); | |
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"); | |
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 } | |
320 } | |
321 } | 417 } |
322 } | 418 } |
323 | 419 |
324 /* Print ipa_jump_func data structures of all nodes in the call graph to F. */ | 420 /* Print ipa_jump_func data structures of all nodes in the call graph to F. */ |
325 | 421 |
333 { | 429 { |
334 ipa_print_node_jump_functions (f, node); | 430 ipa_print_node_jump_functions (f, node); |
335 } | 431 } |
336 } | 432 } |
337 | 433 |
338 /* Determine whether passing ssa name NAME constitutes a polynomial | 434 /* Given that an actual argument is an SSA_NAME (given in NAME) and is a result |
339 pass-through function or getting an address of an acestor and if so, write | 435 of an assignment statement STMT, try to find out whether NAME can be |
340 such a jump function to JFUNC. INFO describes the caller. */ | 436 described by a (possibly polynomial) pass-through jump-function or an |
341 | 437 ancestor jump function and if so, write the appropriate function into |
342 static void | 438 JFUNC */ |
343 compute_complex_pass_through (struct ipa_node_params *info, | 439 |
344 struct ipa_jump_func *jfunc, | 440 static void |
345 tree name) | 441 compute_complex_assign_jump_func (struct ipa_node_params *info, |
442 struct ipa_jump_func *jfunc, | |
443 gimple stmt, tree name) | |
346 { | 444 { |
347 HOST_WIDE_INT offset, size, max_size; | 445 HOST_WIDE_INT offset, size, max_size; |
348 tree op1, op2, type; | 446 tree op1, op2, type; |
349 int index; | 447 int index; |
350 gimple stmt = SSA_NAME_DEF_STMT (name); | 448 |
351 | |
352 if (!is_gimple_assign (stmt)) | |
353 return; | |
354 op1 = gimple_assign_rhs1 (stmt); | 449 op1 = gimple_assign_rhs1 (stmt); |
355 op2 = gimple_assign_rhs2 (stmt); | 450 op2 = gimple_assign_rhs2 (stmt); |
356 | 451 |
357 if (op2) | 452 if (TREE_CODE (op1) == SSA_NAME |
358 { | 453 && SSA_NAME_IS_DEFAULT_DEF (op1)) |
359 if (TREE_CODE (op1) != SSA_NAME | 454 { |
360 || !SSA_NAME_IS_DEFAULT_DEF (op1) | 455 index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); |
361 || (TREE_CODE_CLASS (gimple_expr_code (stmt)) != tcc_comparison | 456 if (index < 0) |
362 && !useless_type_conversion_p (TREE_TYPE (name), | |
363 TREE_TYPE (op1))) | |
364 || !is_gimple_ip_invariant (op2)) | |
365 return; | 457 return; |
366 | 458 |
367 index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); | 459 if (op2) |
368 if (index >= 0) | 460 { |
369 { | 461 if (!is_gimple_ip_invariant (op2) |
462 || (TREE_CODE_CLASS (gimple_expr_code (stmt)) != tcc_comparison | |
463 && !useless_type_conversion_p (TREE_TYPE (name), | |
464 TREE_TYPE (op1)))) | |
465 return; | |
466 | |
370 jfunc->type = IPA_JF_PASS_THROUGH; | 467 jfunc->type = IPA_JF_PASS_THROUGH; |
371 jfunc->value.pass_through.formal_id = index; | 468 jfunc->value.pass_through.formal_id = index; |
372 jfunc->value.pass_through.operation = gimple_assign_rhs_code (stmt); | 469 jfunc->value.pass_through.operation = gimple_assign_rhs_code (stmt); |
373 jfunc->value.pass_through.operand = op2; | 470 jfunc->value.pass_through.operand = op2; |
374 } | 471 } |
472 else if (gimple_assign_unary_nop_p (stmt)) | |
473 { | |
474 jfunc->type = IPA_JF_PASS_THROUGH; | |
475 jfunc->value.pass_through.formal_id = index; | |
476 jfunc->value.pass_through.operation = NOP_EXPR; | |
477 } | |
375 return; | 478 return; |
376 } | 479 } |
377 | 480 |
378 if (TREE_CODE (op1) != ADDR_EXPR) | 481 if (TREE_CODE (op1) != ADDR_EXPR) |
379 return; | 482 return; |
483 | |
380 op1 = TREE_OPERAND (op1, 0); | 484 op1 = TREE_OPERAND (op1, 0); |
381 type = TREE_TYPE (op1); | 485 type = TREE_TYPE (op1); |
382 | 486 if (TREE_CODE (type) != RECORD_TYPE) |
487 return; | |
383 op1 = get_ref_base_and_extent (op1, &offset, &size, &max_size); | 488 op1 = get_ref_base_and_extent (op1, &offset, &size, &max_size); |
384 if (TREE_CODE (op1) != INDIRECT_REF | 489 if (TREE_CODE (op1) != INDIRECT_REF |
385 /* If this is a varying address, punt. */ | 490 /* If this is a varying address, punt. */ |
386 || max_size == -1 | 491 || max_size == -1 |
387 || max_size != size) | 492 || max_size != size) |
396 { | 501 { |
397 jfunc->type = IPA_JF_ANCESTOR; | 502 jfunc->type = IPA_JF_ANCESTOR; |
398 jfunc->value.ancestor.formal_id = index; | 503 jfunc->value.ancestor.formal_id = index; |
399 jfunc->value.ancestor.offset = offset; | 504 jfunc->value.ancestor.offset = offset; |
400 jfunc->value.ancestor.type = type; | 505 jfunc->value.ancestor.type = type; |
506 } | |
507 } | |
508 | |
509 | |
510 /* Given that an actual argument is an SSA_NAME that is a result of a phi | |
511 statement PHI, try to find out whether NAME is in fact a | |
512 multiple-inheritance typecast from a descendant into an ancestor of a formal | |
513 parameter and thus can be described by an ancestor jump function and if so, | |
514 write the appropriate function into JFUNC. | |
515 | |
516 Essentially we want to match the following pattern: | |
517 | |
518 if (obj_2(D) != 0B) | |
519 goto <bb 3>; | |
520 else | |
521 goto <bb 4>; | |
522 | |
523 <bb 3>: | |
524 iftmp.1_3 = &obj_2(D)->D.1762; | |
525 | |
526 <bb 4>: | |
527 # iftmp.1_1 = PHI <iftmp.1_3(3), 0B(2)> | |
528 D.1879_6 = middleman_1 (iftmp.1_1, i_5(D)); | |
529 return D.1879_6; */ | |
530 | |
531 static void | |
532 compute_complex_ancestor_jump_func (struct ipa_node_params *info, | |
533 struct ipa_jump_func *jfunc, | |
534 gimple phi) | |
535 { | |
536 HOST_WIDE_INT offset, size, max_size; | |
537 gimple assign, cond; | |
538 basic_block phi_bb, assign_bb, cond_bb; | |
539 tree tmp, parm, expr; | |
540 int index, i; | |
541 | |
542 if (gimple_phi_num_args (phi) != 2 | |
543 || !integer_zerop (PHI_ARG_DEF (phi, 1))) | |
544 return; | |
545 | |
546 tmp = PHI_ARG_DEF (phi, 0); | |
547 if (TREE_CODE (tmp) != SSA_NAME | |
548 || SSA_NAME_IS_DEFAULT_DEF (tmp) | |
549 || !POINTER_TYPE_P (TREE_TYPE (tmp)) | |
550 || TREE_CODE (TREE_TYPE (TREE_TYPE (tmp))) != RECORD_TYPE) | |
551 return; | |
552 | |
553 assign = SSA_NAME_DEF_STMT (tmp); | |
554 assign_bb = gimple_bb (assign); | |
555 if (!single_pred_p (assign_bb) | |
556 || !gimple_assign_single_p (assign)) | |
557 return; | |
558 expr = gimple_assign_rhs1 (assign); | |
559 | |
560 if (TREE_CODE (expr) != ADDR_EXPR) | |
561 return; | |
562 expr = TREE_OPERAND (expr, 0); | |
563 expr = get_ref_base_and_extent (expr, &offset, &size, &max_size); | |
564 | |
565 if (TREE_CODE (expr) != INDIRECT_REF | |
566 /* If this is a varying address, punt. */ | |
567 || max_size == -1 | |
568 || max_size != size) | |
569 return; | |
570 parm = TREE_OPERAND (expr, 0); | |
571 if (TREE_CODE (parm) != SSA_NAME | |
572 || !SSA_NAME_IS_DEFAULT_DEF (parm)) | |
573 return; | |
574 | |
575 index = ipa_get_param_decl_index (info, SSA_NAME_VAR (parm)); | |
576 if (index < 0) | |
577 return; | |
578 | |
579 cond_bb = single_pred (assign_bb); | |
580 cond = last_stmt (cond_bb); | |
581 if (!cond | |
582 || gimple_code (cond) != GIMPLE_COND | |
583 || gimple_cond_code (cond) != NE_EXPR | |
584 || gimple_cond_lhs (cond) != parm | |
585 || !integer_zerop (gimple_cond_rhs (cond))) | |
586 return; | |
587 | |
588 | |
589 phi_bb = gimple_bb (phi); | |
590 for (i = 0; i < 2; i++) | |
591 { | |
592 basic_block pred = EDGE_PRED (phi_bb, i)->src; | |
593 if (pred != assign_bb && pred != cond_bb) | |
594 return; | |
595 } | |
596 | |
597 jfunc->type = IPA_JF_ANCESTOR; | |
598 jfunc->value.ancestor.formal_id = index; | |
599 jfunc->value.ancestor.offset = offset; | |
600 jfunc->value.ancestor.type = TREE_TYPE (TREE_TYPE (tmp)); | |
601 } | |
602 | |
603 /* Given OP whch is passed as an actual argument to a called function, | |
604 determine if it is possible to construct a KNOWN_TYPE jump function for it | |
605 and if so, create one and store it to JFUNC. */ | |
606 | |
607 static void | |
608 compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc) | |
609 { | |
610 tree binfo; | |
611 | |
612 if (TREE_CODE (op) != ADDR_EXPR) | |
613 return; | |
614 | |
615 op = TREE_OPERAND (op, 0); | |
616 binfo = gimple_get_relevant_ref_binfo (op, NULL_TREE); | |
617 if (binfo) | |
618 { | |
619 jfunc->type = IPA_JF_KNOWN_TYPE; | |
620 jfunc->value.base_binfo = binfo; | |
401 } | 621 } |
402 } | 622 } |
403 | 623 |
404 | 624 |
405 /* Determine the jump functions of scalar arguments. Scalar means SSA names | 625 /* Determine the jump functions of scalar arguments. Scalar means SSA names |
437 functions[num].value.pass_through.formal_id = index; | 657 functions[num].value.pass_through.formal_id = index; |
438 functions[num].value.pass_through.operation = NOP_EXPR; | 658 functions[num].value.pass_through.operation = NOP_EXPR; |
439 } | 659 } |
440 } | 660 } |
441 else | 661 else |
442 compute_complex_pass_through (info, &functions[num], arg); | 662 { |
443 } | 663 gimple stmt = SSA_NAME_DEF_STMT (arg); |
664 if (is_gimple_assign (stmt)) | |
665 compute_complex_assign_jump_func (info, &functions[num], | |
666 stmt, arg); | |
667 else if (gimple_code (stmt) == GIMPLE_PHI) | |
668 compute_complex_ancestor_jump_func (info, &functions[num], | |
669 stmt); | |
670 } | |
671 } | |
672 else | |
673 compute_known_type_jump_func (arg, &functions[num]); | |
444 } | 674 } |
445 } | 675 } |
446 | 676 |
447 /* Inspect the given TYPE and return true iff it has the same structure (the | 677 /* Inspect the given TYPE and return true iff it has the same structure (the |
448 same number of fields of the same types) as a C++ member pointer. If | 678 same number of fields of the same types) as a C++ member pointer. If |
651 | 881 |
652 /* Compute jump function for all arguments of callsite CS and insert the | 882 /* Compute jump function for all arguments of callsite CS and insert the |
653 information in the jump_functions array in the ipa_edge_args corresponding | 883 information in the jump_functions array in the ipa_edge_args corresponding |
654 to this callsite. */ | 884 to this callsite. */ |
655 | 885 |
656 void | 886 static void |
657 ipa_compute_jump_functions (struct cgraph_edge *cs) | 887 ipa_compute_jump_functions_for_edge (struct cgraph_edge *cs) |
658 { | 888 { |
659 struct ipa_node_params *info = IPA_NODE_REF (cs->caller); | 889 struct ipa_node_params *info = IPA_NODE_REF (cs->caller); |
660 struct ipa_edge_args *arguments = IPA_EDGE_REF (cs); | 890 struct ipa_edge_args *arguments = IPA_EDGE_REF (cs); |
661 gimple call; | 891 gimple call; |
662 | 892 |
677 return; | 907 return; |
678 | 908 |
679 /* Finally, let's check whether we actually pass a new constant member | 909 /* Finally, let's check whether we actually pass a new constant member |
680 pointer here... */ | 910 pointer here... */ |
681 compute_cst_member_ptr_arguments (arguments->jump_functions, call); | 911 compute_cst_member_ptr_arguments (arguments->jump_functions, call); |
912 } | |
913 | |
914 /* Compute jump functions for all edges - both direct and indirect - outgoing | |
915 from NODE. Also count the actual arguments in the process. */ | |
916 | |
917 void | |
918 ipa_compute_jump_functions (struct cgraph_node *node) | |
919 { | |
920 struct cgraph_edge *cs; | |
921 | |
922 for (cs = node->callees; cs; cs = cs->next_callee) | |
923 { | |
924 /* We do not need to bother analyzing calls to unknown | |
925 functions unless they may become known during lto/whopr. */ | |
926 if (!cs->callee->analyzed && !flag_lto && !flag_whopr) | |
927 continue; | |
928 ipa_count_arguments (cs); | |
929 if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) | |
930 != ipa_get_param_count (IPA_NODE_REF (cs->callee))) | |
931 ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee)); | |
932 ipa_compute_jump_functions_for_edge (cs); | |
933 } | |
934 | |
935 for (cs = node->indirect_calls; cs; cs = cs->next_callee) | |
936 { | |
937 ipa_count_arguments (cs); | |
938 ipa_compute_jump_functions_for_edge (cs); | |
939 } | |
682 } | 940 } |
683 | 941 |
684 /* If RHS looks like a rhs of a statement loading pfn from a member | 942 /* If RHS looks like a rhs of a statement loading pfn from a member |
685 pointer formal parameter, return the parameter, otherwise return | 943 pointer formal parameter, return the parameter, otherwise return |
686 NULL. If USE_DELTA, then we look for a use of the delta field | 944 NULL. If USE_DELTA, then we look for a use of the delta field |
733 return true; | 991 return true; |
734 else | 992 else |
735 return false; | 993 return false; |
736 } | 994 } |
737 | 995 |
738 /* Creates a new note describing a call to a parameter number FORMAL_ID and | 996 /* Find the indirect call graph edge corresponding to STMT and add to it all |
739 attaches it to the linked list of INFO. It also sets the called flag of the | 997 information necessary to describe a call to a parameter number PARAM_INDEX. |
740 parameter. STMT is the corresponding call statement. */ | 998 NODE is the caller. POLYMORPHIC should be set to true iff the call is a |
741 | 999 virtual one. */ |
742 static void | 1000 |
743 ipa_note_param_call (struct ipa_node_params *info, int formal_id, | 1001 static void |
744 gimple stmt) | 1002 ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt, |
745 { | 1003 bool polymorphic) |
746 struct ipa_param_call_note *note; | 1004 { |
747 basic_block bb = gimple_bb (stmt); | 1005 struct cgraph_edge *cs; |
748 | 1006 |
749 info->params[formal_id].called = 1; | 1007 cs = cgraph_edge (node, stmt); |
750 | 1008 cs->indirect_info->param_index = param_index; |
751 note = XCNEW (struct ipa_param_call_note); | 1009 cs->indirect_info->anc_offset = 0; |
752 note->formal_id = formal_id; | 1010 cs->indirect_info->polymorphic = polymorphic; |
753 note->stmt = stmt; | 1011 if (polymorphic) |
754 note->lto_stmt_uid = gimple_uid (stmt); | 1012 { |
755 note->count = bb->count; | 1013 tree otr = gimple_call_fn (stmt); |
756 note->frequency = compute_call_stmt_bb_frequency (current_function_decl, bb); | 1014 tree type, token = OBJ_TYPE_REF_TOKEN (otr); |
757 note->loop_nest = bb->loop_depth; | 1015 cs->indirect_info->otr_token = tree_low_cst (token, 1); |
758 | 1016 type = TREE_TYPE (TREE_TYPE (OBJ_TYPE_REF_OBJECT (otr))); |
759 note->next = info->param_calls; | 1017 cs->indirect_info->otr_type = type; |
760 info->param_calls = note; | 1018 } |
761 | 1019 } |
762 return; | 1020 |
763 } | 1021 /* Analyze the CALL and examine uses of formal parameters of the caller NODE |
764 | |
765 /* Analyze the CALL and examine uses of formal parameters of the caller | |
766 (described by INFO). Currently it checks whether the call calls a pointer | 1022 (described by INFO). Currently it checks whether the call calls a pointer |
767 that is a formal parameter and if so, the parameter is marked with the | 1023 that is a formal parameter and if so, the parameter is marked with the |
768 called flag and a note describing the call is created. This is very simple | 1024 called flag and an indirect call graph edge describing the call is created. |
769 for ordinary pointers represented in SSA but not-so-nice when it comes to | 1025 This is very simple for ordinary pointers represented in SSA but not-so-nice |
770 member pointers. The ugly part of this function does nothing more than | 1026 when it comes to member pointers. The ugly part of this function does |
771 tries to match the pattern of such a call. An example of such a pattern is | 1027 nothing more than trying to match the pattern of such a call. An example of |
772 the gimple dump below, the call is on the last line: | 1028 such a pattern is the gimple dump below, the call is on the last line: |
773 | 1029 |
774 <bb 2>: | 1030 <bb 2>: |
775 f$__delta_5 = f.__delta; | 1031 f$__delta_5 = f.__delta; |
776 f$__pfn_24 = f.__pfn; | 1032 f$__pfn_24 = f.__pfn; |
777 D.2496_3 = (int) f$__pfn_24; | 1033 D.2496_3 = (int) f$__pfn_24; |
807 return (S.*f)(4); | 1063 return (S.*f)(4); |
808 } | 1064 } |
809 */ | 1065 */ |
810 | 1066 |
811 static void | 1067 static void |
812 ipa_analyze_call_uses (struct ipa_node_params *info, gimple call) | 1068 ipa_analyze_indirect_call_uses (struct cgraph_node *node, |
813 { | 1069 struct ipa_node_params *info, |
814 tree target = gimple_call_fn (call); | 1070 gimple call, tree target) |
1071 { | |
815 gimple def; | 1072 gimple def; |
816 tree var; | |
817 tree n1, n2; | 1073 tree n1, n2; |
818 gimple d1, d2; | 1074 gimple d1, d2; |
819 tree rec, rec2, cond; | 1075 tree rec, rec2, cond; |
820 gimple branch; | 1076 gimple branch; |
821 int index; | 1077 int index; |
822 basic_block bb, virt_bb, join; | 1078 basic_block bb, virt_bb, join; |
823 | 1079 |
824 if (TREE_CODE (target) != SSA_NAME) | |
825 return; | |
826 | |
827 var = SSA_NAME_VAR (target); | |
828 if (SSA_NAME_IS_DEFAULT_DEF (target)) | 1080 if (SSA_NAME_IS_DEFAULT_DEF (target)) |
829 { | 1081 { |
830 /* assuming TREE_CODE (var) == PARM_DECL */ | 1082 tree var = SSA_NAME_VAR (target); |
831 index = ipa_get_param_decl_index (info, var); | 1083 index = ipa_get_param_decl_index (info, var); |
832 if (index >= 0) | 1084 if (index >= 0) |
833 ipa_note_param_call (info, index, call); | 1085 ipa_note_param_call (node, index, call, false); |
834 return; | 1086 return; |
835 } | 1087 } |
836 | 1088 |
837 /* Now we need to try to match the complex pattern of calling a member | 1089 /* Now we need to try to match the complex pattern of calling a member |
838 pointer. */ | 1090 pointer. */ |
925 if (rec != rec2) | 1177 if (rec != rec2) |
926 return; | 1178 return; |
927 | 1179 |
928 index = ipa_get_param_decl_index (info, rec); | 1180 index = ipa_get_param_decl_index (info, rec); |
929 if (index >= 0 && !ipa_is_param_modified (info, index)) | 1181 if (index >= 0 && !ipa_is_param_modified (info, index)) |
930 ipa_note_param_call (info, index, call); | 1182 ipa_note_param_call (node, index, call, false); |
931 | 1183 |
932 return; | 1184 return; |
933 } | 1185 } |
934 | 1186 |
935 /* Analyze the statement STMT with respect to formal parameters (described in | 1187 /* Analyze a CALL to an OBJ_TYPE_REF which is passed in TARGET and if the |
936 INFO) and their uses. Currently it only checks whether formal parameters | 1188 object referenced in the expression is a formal parameter of the caller |
937 are called. */ | 1189 (described by INFO), create a call note for the statement. */ |
938 | 1190 |
939 static void | 1191 static void |
940 ipa_analyze_stmt_uses (struct ipa_node_params *info, gimple stmt) | 1192 ipa_analyze_virtual_call_uses (struct cgraph_node *node, |
1193 struct ipa_node_params *info, gimple call, | |
1194 tree target) | |
1195 { | |
1196 tree obj = OBJ_TYPE_REF_OBJECT (target); | |
1197 tree var; | |
1198 int index; | |
1199 | |
1200 if (TREE_CODE (obj) == ADDR_EXPR) | |
1201 { | |
1202 do | |
1203 { | |
1204 obj = TREE_OPERAND (obj, 0); | |
1205 } | |
1206 while (TREE_CODE (obj) == COMPONENT_REF); | |
1207 if (TREE_CODE (obj) != INDIRECT_REF) | |
1208 return; | |
1209 obj = TREE_OPERAND (obj, 0); | |
1210 } | |
1211 | |
1212 if (TREE_CODE (obj) != SSA_NAME | |
1213 || !SSA_NAME_IS_DEFAULT_DEF (obj)) | |
1214 return; | |
1215 | |
1216 var = SSA_NAME_VAR (obj); | |
1217 index = ipa_get_param_decl_index (info, var); | |
1218 | |
1219 if (index >= 0) | |
1220 ipa_note_param_call (node, index, call, true); | |
1221 } | |
1222 | |
1223 /* Analyze a call statement CALL whether and how it utilizes formal parameters | |
1224 of the caller (described by INFO). */ | |
1225 | |
1226 static void | |
1227 ipa_analyze_call_uses (struct cgraph_node *node, | |
1228 struct ipa_node_params *info, gimple call) | |
1229 { | |
1230 tree target = gimple_call_fn (call); | |
1231 | |
1232 if (TREE_CODE (target) == SSA_NAME) | |
1233 ipa_analyze_indirect_call_uses (node, info, call, target); | |
1234 else if (TREE_CODE (target) == OBJ_TYPE_REF) | |
1235 ipa_analyze_virtual_call_uses (node, info, call, target); | |
1236 } | |
1237 | |
1238 | |
1239 /* Analyze the call statement STMT with respect to formal parameters (described | |
1240 in INFO) of caller given by NODE. Currently it only checks whether formal | |
1241 parameters are called. */ | |
1242 | |
1243 static void | |
1244 ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info, | |
1245 gimple stmt) | |
941 { | 1246 { |
942 if (is_gimple_call (stmt)) | 1247 if (is_gimple_call (stmt)) |
943 ipa_analyze_call_uses (info, stmt); | 1248 ipa_analyze_call_uses (node, info, stmt); |
944 } | 1249 } |
945 | 1250 |
946 /* Scan the function body of NODE and inspect the uses of formal parameters. | 1251 /* Scan the function body of NODE and inspect the uses of formal parameters. |
947 Store the findings in various structures of the associated ipa_node_params | 1252 Store the findings in various structures of the associated ipa_node_params |
948 structure, such as parameter flags, notes etc. */ | 1253 structure, such as parameter flags, notes etc. */ |
963 FOR_EACH_BB_FN (bb, func) | 1268 FOR_EACH_BB_FN (bb, func) |
964 { | 1269 { |
965 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 1270 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
966 { | 1271 { |
967 gimple stmt = gsi_stmt (gsi); | 1272 gimple stmt = gsi_stmt (gsi); |
968 ipa_analyze_stmt_uses (info, stmt); | 1273 ipa_analyze_stmt_uses (node, info, stmt); |
969 } | 1274 } |
970 } | 1275 } |
971 | 1276 |
972 info->uses_analysis_done = 1; | 1277 info->uses_analysis_done = 1; |
1278 } | |
1279 | |
1280 /* Update the jump function DST when the call graph edge correspondng to SRC is | |
1281 is being inlined, knowing that DST is of type ancestor and src of known | |
1282 type. */ | |
1283 | |
1284 static void | |
1285 combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src, | |
1286 struct ipa_jump_func *dst) | |
1287 { | |
1288 tree new_binfo; | |
1289 | |
1290 new_binfo = get_binfo_at_offset (src->value.base_binfo, | |
1291 dst->value.ancestor.offset, | |
1292 dst->value.ancestor.type); | |
1293 if (new_binfo) | |
1294 { | |
1295 dst->type = IPA_JF_KNOWN_TYPE; | |
1296 dst->value.base_binfo = new_binfo; | |
1297 } | |
1298 else | |
1299 dst->type = IPA_JF_UNKNOWN; | |
973 } | 1300 } |
974 | 1301 |
975 /* Update the jump functions associated with call graph edge E when the call | 1302 /* Update the jump functions associated with call graph edge E when the call |
976 graph edge CS is being inlined, assuming that E->caller is already (possibly | 1303 graph edge CS is being inlined, assuming that E->caller is already (possibly |
977 indirectly) inlined into CS->callee and that E has not been inlined. | 1304 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. */ | |
981 | 1305 |
982 static void | 1306 static void |
983 update_jump_functions_after_inlining (struct cgraph_edge *cs, | 1307 update_jump_functions_after_inlining (struct cgraph_edge *cs, |
984 struct cgraph_edge *e) | 1308 struct cgraph_edge *e) |
985 { | 1309 { |
988 int count = ipa_get_cs_argument_count (args); | 1312 int count = ipa_get_cs_argument_count (args); |
989 int i; | 1313 int i; |
990 | 1314 |
991 for (i = 0; i < count; i++) | 1315 for (i = 0; i < count; i++) |
992 { | 1316 { |
993 struct ipa_jump_func *src, *dst = ipa_get_ith_jump_func (args, i); | 1317 struct ipa_jump_func *dst = ipa_get_ith_jump_func (args, i); |
994 | 1318 |
995 if (dst->type == IPA_JF_ANCESTOR) | 1319 if (dst->type == IPA_JF_ANCESTOR) |
996 { | 1320 { |
997 dst->type = IPA_JF_UNKNOWN; | 1321 struct ipa_jump_func *src; |
998 continue; | 1322 |
999 } | 1323 /* Variable number of arguments can cause havoc if we try to access |
1000 | 1324 one that does not exist in the inlined edge. So make sure we |
1001 if (dst->type != IPA_JF_PASS_THROUGH) | 1325 don't. */ |
1002 continue; | 1326 if (dst->value.ancestor.formal_id >= ipa_get_cs_argument_count (top)) |
1003 | 1327 { |
1004 /* We must check range due to calls with variable number of arguments and | 1328 dst->type = IPA_JF_UNKNOWN; |
1005 we cannot combine jump functions with operations. */ | 1329 continue; |
1006 if (dst->value.pass_through.operation != NOP_EXPR | 1330 } |
1007 || (dst->value.pass_through.formal_id | 1331 |
1008 >= ipa_get_cs_argument_count (top))) | 1332 src = ipa_get_ith_jump_func (top, dst->value.ancestor.formal_id); |
1009 { | 1333 if (src->type == IPA_JF_KNOWN_TYPE) |
1010 dst->type = IPA_JF_UNKNOWN; | 1334 combine_known_type_and_ancestor_jfs (src, dst); |
1011 continue; | 1335 else if (src->type == IPA_JF_CONST) |
1012 } | 1336 { |
1013 | 1337 struct ipa_jump_func kt_func; |
1014 src = ipa_get_ith_jump_func (top, dst->value.pass_through.formal_id); | 1338 |
1015 *dst = *src; | 1339 kt_func.type = IPA_JF_UNKNOWN; |
1016 } | 1340 compute_known_type_jump_func (src->value.constant, &kt_func); |
1017 } | 1341 if (kt_func.type == IPA_JF_KNOWN_TYPE) |
1018 | 1342 combine_known_type_and_ancestor_jfs (&kt_func, dst); |
1019 /* Print out a debug message to file F that we have discovered that an indirect | 1343 else |
1020 call described by NT is in fact a call of a known constant function described | 1344 dst->type = IPA_JF_UNKNOWN; |
1021 by JFUNC. NODE is the node where the call is. */ | 1345 } |
1022 | 1346 else if (src->type == IPA_JF_PASS_THROUGH |
1023 static void | 1347 && src->value.pass_through.operation == NOP_EXPR) |
1024 print_edge_addition_message (FILE *f, struct ipa_param_call_note *nt, | 1348 dst->value.ancestor.formal_id = src->value.pass_through.formal_id; |
1025 struct ipa_jump_func *jfunc, | 1349 else if (src->type == IPA_JF_ANCESTOR) |
1026 struct cgraph_node *node) | 1350 { |
1027 { | 1351 dst->value.ancestor.formal_id = src->value.ancestor.formal_id; |
1028 fprintf (f, "ipa-prop: Discovered an indirect call to a known target ("); | 1352 dst->value.ancestor.offset += src->value.ancestor.offset; |
1029 if (jfunc->type == IPA_JF_CONST_MEMBER_PTR) | 1353 } |
1030 { | 1354 else |
1031 print_node_brief (f, "", jfunc->value.member_cst.pfn, 0); | 1355 dst->type = IPA_JF_UNKNOWN; |
1032 print_node_brief (f, ", ", jfunc->value.member_cst.delta, 0); | 1356 } |
1033 } | 1357 else if (dst->type == IPA_JF_PASS_THROUGH) |
1358 { | |
1359 struct ipa_jump_func *src; | |
1360 /* We must check range due to calls with variable number of arguments | |
1361 and we cannot combine jump functions with operations. */ | |
1362 if (dst->value.pass_through.operation == NOP_EXPR | |
1363 && (dst->value.pass_through.formal_id | |
1364 < ipa_get_cs_argument_count (top))) | |
1365 { | |
1366 src = ipa_get_ith_jump_func (top, | |
1367 dst->value.pass_through.formal_id); | |
1368 *dst = *src; | |
1369 } | |
1370 else | |
1371 dst->type = IPA_JF_UNKNOWN; | |
1372 } | |
1373 } | |
1374 } | |
1375 | |
1376 /* If TARGET is an addr_expr of a function declaration, make it the destination | |
1377 of an indirect edge IE and return the edge. Otherwise, return NULL. */ | |
1378 | |
1379 static struct cgraph_edge * | |
1380 make_edge_direct_to_target (struct cgraph_edge *ie, tree target) | |
1381 { | |
1382 struct cgraph_node *callee; | |
1383 | |
1384 if (TREE_CODE (target) != ADDR_EXPR) | |
1385 return NULL; | |
1386 target = TREE_OPERAND (target, 0); | |
1387 if (TREE_CODE (target) != FUNCTION_DECL) | |
1388 return NULL; | |
1389 callee = cgraph_node (target); | |
1390 if (!callee) | |
1391 return NULL; | |
1392 | |
1393 cgraph_make_edge_direct (ie, callee); | |
1394 if (dump_file) | |
1395 { | |
1396 fprintf (dump_file, "ipa-prop: Discovered %s call to a known target " | |
1397 "(%s/%i -> %s/%i) for stmt ", | |
1398 ie->indirect_info->polymorphic ? "a virtual" : "an indirect", | |
1399 cgraph_node_name (ie->caller), ie->caller->uid, | |
1400 cgraph_node_name (ie->callee), ie->callee->uid); | |
1401 | |
1402 if (ie->call_stmt) | |
1403 print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM); | |
1404 else | |
1405 fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid); | |
1406 } | |
1407 | |
1408 if (ipa_get_cs_argument_count (IPA_EDGE_REF (ie)) | |
1409 != ipa_get_param_count (IPA_NODE_REF (callee))) | |
1410 ipa_set_called_with_variable_arg (IPA_NODE_REF (callee)); | |
1411 | |
1412 return ie; | |
1413 } | |
1414 | |
1415 /* Try to find a destination for indirect edge IE that corresponds to a simple | |
1416 call or a call of a member function pointer and where the destination is a | |
1417 pointer formal parameter described by jump function JFUNC. If it can be | |
1418 determined, return the newly direct edge, otherwise return NULL. */ | |
1419 | |
1420 static struct cgraph_edge * | |
1421 try_make_edge_direct_simple_call (struct cgraph_edge *ie, | |
1422 struct ipa_jump_func *jfunc) | |
1423 { | |
1424 tree target; | |
1425 | |
1426 if (jfunc->type == IPA_JF_CONST) | |
1427 target = jfunc->value.constant; | |
1428 else if (jfunc->type == IPA_JF_CONST_MEMBER_PTR) | |
1429 target = jfunc->value.member_cst.pfn; | |
1034 else | 1430 else |
1035 print_node_brief(f, "", jfunc->value.constant, 0); | 1431 return NULL; |
1036 | 1432 |
1037 fprintf (f, ") in %s: ", cgraph_node_name (node)); | 1433 return make_edge_direct_to_target (ie, target); |
1038 print_gimple_stmt (f, nt->stmt, 2, TDF_SLIM); | 1434 } |
1435 | |
1436 /* Try to find a destination for indirect edge IE that corresponds to a | |
1437 virtuall call based on a formal parameter which is described by jump | |
1438 function JFUNC and if it can be determined, make it direct and return the | |
1439 direct edge. Otherwise, return NULL. */ | |
1440 | |
1441 static struct cgraph_edge * | |
1442 try_make_edge_direct_virtual_call (struct cgraph_edge *ie, | |
1443 struct ipa_jump_func *jfunc) | |
1444 { | |
1445 tree binfo, type, target; | |
1446 HOST_WIDE_INT token; | |
1447 | |
1448 if (jfunc->type == IPA_JF_KNOWN_TYPE) | |
1449 binfo = jfunc->value.base_binfo; | |
1450 else if (jfunc->type == IPA_JF_CONST) | |
1451 { | |
1452 tree cst = jfunc->value.constant; | |
1453 if (TREE_CODE (cst) == ADDR_EXPR) | |
1454 binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (cst, 0), | |
1455 NULL_TREE); | |
1456 else | |
1457 return NULL; | |
1458 } | |
1459 else | |
1460 return NULL; | |
1461 | |
1462 if (!binfo) | |
1463 return NULL; | |
1464 | |
1465 token = ie->indirect_info->otr_token; | |
1466 type = ie->indirect_info->otr_type; | |
1467 binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type); | |
1468 if (binfo) | |
1469 target = gimple_fold_obj_type_ref_known_binfo (token, binfo); | |
1470 else | |
1471 return NULL; | |
1472 | |
1473 if (target) | |
1474 return make_edge_direct_to_target (ie, target); | |
1475 else | |
1476 return NULL; | |
1039 } | 1477 } |
1040 | 1478 |
1041 /* Update the param called notes associated with NODE when CS is being inlined, | 1479 /* Update the param called notes associated with NODE when CS is being inlined, |
1042 assuming NODE is (potentially indirectly) inlined into CS->callee. | 1480 assuming NODE is (potentially indirectly) inlined into CS->callee. |
1043 Moreover, if the callee is discovered to be constant, create a new cgraph | 1481 Moreover, if the callee is discovered to be constant, create a new cgraph |
1044 edge for it. Newly discovered indirect edges will be added to *NEW_EDGES, | 1482 edge for it. Newly discovered indirect edges will be added to *NEW_EDGES, |
1045 unless NEW_EDGES is NULL. Return true iff a new edge(s) were created. */ | 1483 unless NEW_EDGES is NULL. Return true iff a new edge(s) were created. */ |
1046 | 1484 |
1047 static bool | 1485 static bool |
1048 update_call_notes_after_inlining (struct cgraph_edge *cs, | 1486 update_indirect_edges_after_inlining (struct cgraph_edge *cs, |
1049 struct cgraph_node *node, | 1487 struct cgraph_node *node, |
1050 VEC (cgraph_edge_p, heap) **new_edges) | 1488 VEC (cgraph_edge_p, heap) **new_edges) |
1051 { | 1489 { |
1052 struct ipa_node_params *info = IPA_NODE_REF (node); | |
1053 struct ipa_edge_args *top = IPA_EDGE_REF (cs); | 1490 struct ipa_edge_args *top = IPA_EDGE_REF (cs); |
1054 struct ipa_param_call_note *nt; | 1491 struct cgraph_edge *ie, *next_ie, *new_direct_edge; |
1055 bool res = false; | 1492 bool res = false; |
1056 | 1493 |
1057 for (nt = info->param_calls; nt; nt = nt->next) | 1494 ipa_check_create_edge_args (); |
1058 { | 1495 |
1496 for (ie = node->indirect_calls; ie; ie = next_ie) | |
1497 { | |
1498 struct cgraph_indirect_call_info *ici = ie->indirect_info; | |
1059 struct ipa_jump_func *jfunc; | 1499 struct ipa_jump_func *jfunc; |
1060 | 1500 |
1061 if (nt->processed) | 1501 next_ie = ie->next_callee; |
1502 if (bitmap_bit_p (iinlining_processed_edges, ie->uid)) | |
1062 continue; | 1503 continue; |
1063 | 1504 |
1505 /* If we ever use indirect edges for anything other than indirect | |
1506 inlining, we will need to skip those with negative param_indices. */ | |
1507 if (ici->param_index == -1) | |
1508 continue; | |
1509 | |
1064 /* We must check range due to calls with variable number of arguments: */ | 1510 /* We must check range due to calls with variable number of arguments: */ |
1065 if (nt->formal_id >= ipa_get_cs_argument_count (top)) | 1511 if (ici->param_index >= ipa_get_cs_argument_count (top)) |
1066 { | 1512 { |
1067 nt->processed = true; | 1513 bitmap_set_bit (iinlining_processed_edges, ie->uid); |
1068 continue; | 1514 continue; |
1069 } | 1515 } |
1070 | 1516 |
1071 jfunc = ipa_get_ith_jump_func (top, nt->formal_id); | 1517 jfunc = ipa_get_ith_jump_func (top, ici->param_index); |
1072 if (jfunc->type == IPA_JF_PASS_THROUGH | 1518 if (jfunc->type == IPA_JF_PASS_THROUGH |
1073 && jfunc->value.pass_through.operation == NOP_EXPR) | 1519 && jfunc->value.pass_through.operation == NOP_EXPR) |
1074 nt->formal_id = jfunc->value.pass_through.formal_id; | 1520 ici->param_index = jfunc->value.pass_through.formal_id; |
1075 else if (jfunc->type == IPA_JF_CONST | 1521 else if (jfunc->type == IPA_JF_ANCESTOR) |
1076 || jfunc->type == IPA_JF_CONST_MEMBER_PTR) | 1522 { |
1077 { | 1523 ici->param_index = jfunc->value.ancestor.formal_id; |
1078 struct cgraph_node *callee; | 1524 ici->anc_offset += jfunc->value.ancestor.offset; |
1079 struct cgraph_edge *new_indirect_edge; | 1525 } |
1080 tree decl; | 1526 else |
1081 | 1527 /* Either we can find a destination for this edge now or never. */ |
1082 nt->processed = true; | 1528 bitmap_set_bit (iinlining_processed_edges, ie->uid); |
1083 if (jfunc->type == IPA_JF_CONST_MEMBER_PTR) | 1529 |
1084 decl = jfunc->value.member_cst.pfn; | 1530 if (ici->polymorphic) |
1085 else | 1531 new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc); |
1086 decl = jfunc->value.constant; | 1532 else |
1087 | 1533 new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc); |
1088 if (TREE_CODE (decl) != ADDR_EXPR) | 1534 |
1089 continue; | 1535 if (new_direct_edge) |
1090 decl = TREE_OPERAND (decl, 0); | 1536 { |
1091 | 1537 new_direct_edge->indirect_inlining_edge = 1; |
1092 if (TREE_CODE (decl) != FUNCTION_DECL) | |
1093 continue; | |
1094 callee = cgraph_node (decl); | |
1095 if (!callee || !callee->local.inlinable) | |
1096 continue; | |
1097 | |
1098 res = true; | |
1099 if (dump_file) | |
1100 print_edge_addition_message (dump_file, nt, jfunc, node); | |
1101 | |
1102 new_indirect_edge = cgraph_create_edge (node, callee, nt->stmt, | |
1103 nt->count, nt->frequency, | |
1104 nt->loop_nest); | |
1105 new_indirect_edge->lto_stmt_uid = nt->lto_stmt_uid; | |
1106 new_indirect_edge->indirect_call = 1; | |
1107 ipa_check_create_edge_args (); | |
1108 if (new_edges) | 1538 if (new_edges) |
1109 VEC_safe_push (cgraph_edge_p, heap, *new_edges, new_indirect_edge); | 1539 { |
1110 top = IPA_EDGE_REF (cs); | 1540 VEC_safe_push (cgraph_edge_p, heap, *new_edges, |
1111 } | 1541 new_direct_edge); |
1112 else | 1542 top = IPA_EDGE_REF (cs); |
1113 { | 1543 res = true; |
1114 /* Ancestor jum functions and pass theoughs with operations should | 1544 } |
1115 not be used on parameters that then get called. */ | 1545 } |
1116 gcc_assert (jfunc->type == IPA_JF_UNKNOWN); | 1546 } |
1117 nt->processed = true; | 1547 |
1118 } | |
1119 } | |
1120 return res; | 1548 return res; |
1121 } | 1549 } |
1122 | 1550 |
1123 /* Recursively traverse subtree of NODE (including node) made of inlined | 1551 /* Recursively traverse subtree of NODE (including node) made of inlined |
1124 cgraph_edges when CS has been inlined and invoke | 1552 cgraph_edges when CS has been inlined and invoke |
1125 update_call_notes_after_inlining on all nodes and | 1553 update_indirect_edges_after_inlining on all nodes and |
1126 update_jump_functions_after_inlining on all non-inlined edges that lead out | 1554 update_jump_functions_after_inlining on all non-inlined edges that lead out |
1127 of this subtree. Newly discovered indirect edges will be added to | 1555 of this subtree. Newly discovered indirect edges will be added to |
1128 *NEW_EDGES, unless NEW_EDGES is NULL. Return true iff a new edge(s) were | 1556 *NEW_EDGES, unless NEW_EDGES is NULL. Return true iff a new edge(s) were |
1129 created. */ | 1557 created. */ |
1130 | 1558 |
1134 VEC (cgraph_edge_p, heap) **new_edges) | 1562 VEC (cgraph_edge_p, heap) **new_edges) |
1135 { | 1563 { |
1136 struct cgraph_edge *e; | 1564 struct cgraph_edge *e; |
1137 bool res; | 1565 bool res; |
1138 | 1566 |
1139 res = update_call_notes_after_inlining (cs, node, new_edges); | 1567 res = update_indirect_edges_after_inlining (cs, node, new_edges); |
1140 | 1568 |
1141 for (e = node->callees; e; e = e->next_callee) | 1569 for (e = node->callees; e; e = e->next_callee) |
1142 if (!e->inline_failed) | 1570 if (!e->inline_failed) |
1143 res |= propagate_info_to_inlined_callees (cs, e->callee, new_edges); | 1571 res |= propagate_info_to_inlined_callees (cs, e->callee, new_edges); |
1144 else | 1572 else |
1206 ipa_free_node_params_substructures (struct ipa_node_params *info) | 1634 ipa_free_node_params_substructures (struct ipa_node_params *info) |
1207 { | 1635 { |
1208 if (info->params) | 1636 if (info->params) |
1209 free (info->params); | 1637 free (info->params); |
1210 | 1638 |
1211 while (info->param_calls) | |
1212 { | |
1213 struct ipa_param_call_note *note = info->param_calls; | |
1214 info->param_calls = note->next; | |
1215 free (note); | |
1216 } | |
1217 | |
1218 memset (info, 0, sizeof (*info)); | 1639 memset (info, 0, sizeof (*info)); |
1219 } | 1640 } |
1220 | 1641 |
1221 /* Free all ipa_node_params structures. */ | 1642 /* Free all ipa_node_params structures. */ |
1222 | 1643 |
1250 /* Hook that is called by cgraph.c when a node is removed. */ | 1671 /* Hook that is called by cgraph.c when a node is removed. */ |
1251 | 1672 |
1252 static void | 1673 static void |
1253 ipa_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | 1674 ipa_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) |
1254 { | 1675 { |
1676 /* During IPA-CP updating we can be called on not-yet analyze clones. */ | |
1677 if (VEC_length (ipa_node_params_t, ipa_node_params_vector) | |
1678 <= (unsigned)node->uid) | |
1679 return; | |
1255 ipa_free_node_params_substructures (IPA_NODE_REF (node)); | 1680 ipa_free_node_params_substructures (IPA_NODE_REF (node)); |
1256 } | 1681 } |
1257 | 1682 |
1258 /* Helper function to duplicate an array of size N that is at SRC and store a | 1683 /* Helper function to duplicate an array of size N that is at SRC and store a |
1259 pointer to it to DST. Nothing is done if SRC is NULL. */ | 1684 pointer to it to DST. Nothing is done if SRC is NULL. */ |
1303 arg_count = ipa_get_cs_argument_count (old_args); | 1728 arg_count = ipa_get_cs_argument_count (old_args); |
1304 ipa_set_cs_argument_count (new_args, arg_count); | 1729 ipa_set_cs_argument_count (new_args, arg_count); |
1305 new_args->jump_functions = (struct ipa_jump_func *) | 1730 new_args->jump_functions = (struct ipa_jump_func *) |
1306 duplicate_ggc_array (old_args->jump_functions, | 1731 duplicate_ggc_array (old_args->jump_functions, |
1307 sizeof (struct ipa_jump_func) * arg_count); | 1732 sizeof (struct ipa_jump_func) * arg_count); |
1733 | |
1734 if (iinlining_processed_edges | |
1735 && bitmap_bit_p (iinlining_processed_edges, src->uid)) | |
1736 bitmap_set_bit (iinlining_processed_edges, dst->uid); | |
1308 } | 1737 } |
1309 | 1738 |
1310 /* Hook that is called by cgraph.c when a node is duplicated. */ | 1739 /* Hook that is called by cgraph.c when a node is duplicated. */ |
1311 | 1740 |
1312 static void | 1741 static void |
1313 ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, | 1742 ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, |
1314 __attribute__((unused)) void *data) | 1743 __attribute__((unused)) void *data) |
1315 { | 1744 { |
1316 struct ipa_node_params *old_info, *new_info; | 1745 struct ipa_node_params *old_info, *new_info; |
1317 struct ipa_param_call_note *note; | |
1318 int param_count; | 1746 int param_count; |
1319 | 1747 |
1320 ipa_check_create_node_params (); | 1748 ipa_check_create_node_params (); |
1321 old_info = IPA_NODE_REF (src); | 1749 old_info = IPA_NODE_REF (src); |
1322 new_info = IPA_NODE_REF (dst); | 1750 new_info = IPA_NODE_REF (dst); |
1326 new_info->params = (struct ipa_param_descriptor *) | 1754 new_info->params = (struct ipa_param_descriptor *) |
1327 duplicate_array (old_info->params, | 1755 duplicate_array (old_info->params, |
1328 sizeof (struct ipa_param_descriptor) * param_count); | 1756 sizeof (struct ipa_param_descriptor) * param_count); |
1329 new_info->ipcp_orig_node = old_info->ipcp_orig_node; | 1757 new_info->ipcp_orig_node = old_info->ipcp_orig_node; |
1330 new_info->count_scale = old_info->count_scale; | 1758 new_info->count_scale = old_info->count_scale; |
1331 | |
1332 for (note = old_info->param_calls; note; note = note->next) | |
1333 { | |
1334 struct ipa_param_call_note *nn; | |
1335 | |
1336 nn = (struct ipa_param_call_note *) | |
1337 xcalloc (1, sizeof (struct ipa_param_call_note)); | |
1338 memcpy (nn, note, sizeof (struct ipa_param_call_note)); | |
1339 nn->next = new_info->param_calls; | |
1340 new_info->param_calls = nn; | |
1341 } | |
1342 } | 1759 } |
1343 | 1760 |
1344 /* Register our cgraph hooks if they are not already there. */ | 1761 /* Register our cgraph hooks if they are not already there. */ |
1345 | 1762 |
1346 void | 1763 void |
1373 edge_duplication_hook_holder = NULL; | 1790 edge_duplication_hook_holder = NULL; |
1374 cgraph_remove_node_duplication_hook (node_duplication_hook_holder); | 1791 cgraph_remove_node_duplication_hook (node_duplication_hook_holder); |
1375 node_duplication_hook_holder = NULL; | 1792 node_duplication_hook_holder = NULL; |
1376 } | 1793 } |
1377 | 1794 |
1795 /* Allocate all necessary data strucutures necessary for indirect inlining. */ | |
1796 | |
1797 void | |
1798 ipa_create_all_structures_for_iinln (void) | |
1799 { | |
1800 iinlining_processed_edges = BITMAP_ALLOC (NULL); | |
1801 } | |
1802 | |
1378 /* Free all ipa_node_params and all ipa_edge_args structures if they are no | 1803 /* Free all ipa_node_params and all ipa_edge_args structures if they are no |
1379 longer needed after ipa-cp. */ | 1804 longer needed after ipa-cp. */ |
1380 | 1805 |
1381 void | 1806 void |
1382 free_all_ipa_structures_after_ipa_cp (void) | 1807 ipa_free_all_structures_after_ipa_cp (void) |
1383 { | 1808 { |
1384 if (!flag_indirect_inlining) | 1809 if (!flag_indirect_inlining) |
1385 { | 1810 { |
1386 ipa_free_all_edge_args (); | 1811 ipa_free_all_edge_args (); |
1387 ipa_free_all_node_params (); | 1812 ipa_free_all_node_params (); |
1391 | 1816 |
1392 /* Free all ipa_node_params and all ipa_edge_args structures if they are no | 1817 /* Free all ipa_node_params and all ipa_edge_args structures if they are no |
1393 longer needed after indirect inlining. */ | 1818 longer needed after indirect inlining. */ |
1394 | 1819 |
1395 void | 1820 void |
1396 free_all_ipa_structures_after_iinln (void) | 1821 ipa_free_all_structures_after_iinln (void) |
1397 { | 1822 { |
1823 BITMAP_FREE (iinlining_processed_edges); | |
1824 | |
1398 ipa_free_all_edge_args (); | 1825 ipa_free_all_edge_args (); |
1399 ipa_free_all_node_params (); | 1826 ipa_free_all_node_params (); |
1400 ipa_unregister_cgraph_hooks (); | 1827 ipa_unregister_cgraph_hooks (); |
1401 } | 1828 } |
1402 | 1829 |
1411 struct ipa_node_params *info; | 1838 struct ipa_node_params *info; |
1412 | 1839 |
1413 if (!node->analyzed) | 1840 if (!node->analyzed) |
1414 return; | 1841 return; |
1415 info = IPA_NODE_REF (node); | 1842 info = IPA_NODE_REF (node); |
1416 fprintf (f, " function %s Trees :: \n", cgraph_node_name (node)); | 1843 fprintf (f, " function %s parameter descriptors:\n", |
1844 cgraph_node_name (node)); | |
1417 count = ipa_get_param_count (info); | 1845 count = ipa_get_param_count (info); |
1418 for (i = 0; i < count; i++) | 1846 for (i = 0; i < count; i++) |
1419 { | 1847 { |
1420 temp = ipa_get_param (info, i); | 1848 temp = ipa_get_param (info, i); |
1421 if (TREE_CODE (temp) == PARM_DECL) | 1849 if (TREE_CODE (temp) == PARM_DECL) |
1423 (DECL_NAME (temp) | 1851 (DECL_NAME (temp) |
1424 ? (*lang_hooks.decl_printable_name) (temp, 2) | 1852 ? (*lang_hooks.decl_printable_name) (temp, 2) |
1425 : "(unnamed)")); | 1853 : "(unnamed)")); |
1426 if (ipa_is_param_modified (info, i)) | 1854 if (ipa_is_param_modified (info, i)) |
1427 fprintf (f, " modified"); | 1855 fprintf (f, " modified"); |
1428 if (ipa_is_param_called (info, i)) | 1856 if (ipa_is_param_used (info, i)) |
1429 fprintf (f, " called"); | 1857 fprintf (f, " used"); |
1430 fprintf (f, "\n"); | 1858 fprintf (f, "\n"); |
1431 } | 1859 } |
1432 } | 1860 } |
1433 | 1861 |
1434 /* Print ipa_tree_map data structures of all functions in the | 1862 /* Print ipa_tree_map data structures of all functions in the |
1692 if (!POINTER_TYPE_P (TREE_TYPE (expr))) | 2120 if (!POINTER_TYPE_P (TREE_TYPE (expr))) |
1693 expr = build_fold_addr_expr (expr); | 2121 expr = build_fold_addr_expr (expr); |
1694 if (!useless_type_conversion_p (ptrtype, TREE_TYPE (expr))) | 2122 if (!useless_type_conversion_p (ptrtype, TREE_TYPE (expr))) |
1695 expr = fold_convert (ptrtype, expr); | 2123 expr = fold_convert (ptrtype, expr); |
1696 expr = fold_build2 (POINTER_PLUS_EXPR, ptrtype, expr, | 2124 expr = fold_build2 (POINTER_PLUS_EXPR, ptrtype, expr, |
1697 build_int_cst (size_type_node, | 2125 build_int_cst (sizetype, |
1698 adj->offset / BITS_PER_UNIT)); | 2126 adj->offset / BITS_PER_UNIT)); |
1699 if (!adj->by_ref) | 2127 if (!adj->by_ref) |
1700 expr = fold_build1 (INDIRECT_REF, adj->type, expr); | 2128 expr = fold_build1 (INDIRECT_REF, adj->type, expr); |
1701 } | 2129 } |
1702 expr = force_gimple_operand_gsi (&gsi, expr, | 2130 expr = force_gimple_operand_gsi (&gsi, expr, |
1904 jump_func->type); | 2332 jump_func->type); |
1905 | 2333 |
1906 switch (jump_func->type) | 2334 switch (jump_func->type) |
1907 { | 2335 { |
1908 case IPA_JF_UNKNOWN: | 2336 case IPA_JF_UNKNOWN: |
2337 break; | |
2338 case IPA_JF_KNOWN_TYPE: | |
2339 lto_output_tree (ob, jump_func->value.base_binfo, true); | |
1909 break; | 2340 break; |
1910 case IPA_JF_CONST: | 2341 case IPA_JF_CONST: |
1911 lto_output_tree (ob, jump_func->value.constant, true); | 2342 lto_output_tree (ob, jump_func->value.constant, true); |
1912 break; | 2343 break; |
1913 case IPA_JF_PASS_THROUGH: | 2344 case IPA_JF_PASS_THROUGH: |
1942 | 2373 |
1943 switch (jump_func->type) | 2374 switch (jump_func->type) |
1944 { | 2375 { |
1945 case IPA_JF_UNKNOWN: | 2376 case IPA_JF_UNKNOWN: |
1946 break; | 2377 break; |
2378 case IPA_JF_KNOWN_TYPE: | |
2379 jump_func->value.base_binfo = lto_input_tree (ib, data_in); | |
2380 break; | |
1947 case IPA_JF_CONST: | 2381 case IPA_JF_CONST: |
1948 jump_func->value.constant = lto_input_tree (ib, data_in); | 2382 jump_func->value.constant = lto_input_tree (ib, data_in); |
1949 break; | 2383 break; |
1950 case IPA_JF_PASS_THROUGH: | 2384 case IPA_JF_PASS_THROUGH: |
1951 jump_func->value.pass_through.operand = lto_input_tree (ib, data_in); | 2385 jump_func->value.pass_through.operand = lto_input_tree (ib, data_in); |
1962 jump_func->value.member_cst.delta = lto_input_tree (ib, data_in); | 2396 jump_func->value.member_cst.delta = lto_input_tree (ib, data_in); |
1963 break; | 2397 break; |
1964 } | 2398 } |
1965 } | 2399 } |
1966 | 2400 |
1967 /* Stream out a parameter call note. */ | 2401 /* Stream out parts of cgraph_indirect_call_info corresponding to CS that are |
1968 | 2402 relevant to indirect inlining to OB. */ |
1969 static void | 2403 |
1970 ipa_write_param_call_note (struct output_block *ob, | 2404 static void |
1971 struct ipa_param_call_note *note) | 2405 ipa_write_indirect_edge_info (struct output_block *ob, |
1972 { | 2406 struct cgraph_edge *cs) |
1973 gcc_assert (!note->processed); | 2407 { |
1974 lto_output_uleb128_stream (ob->main_stream, gimple_uid (note->stmt)); | 2408 struct cgraph_indirect_call_info *ii = cs->indirect_info; |
1975 lto_output_sleb128_stream (ob->main_stream, note->formal_id); | 2409 struct bitpack_d *bp; |
1976 lto_output_sleb128_stream (ob->main_stream, note->count); | 2410 |
1977 lto_output_sleb128_stream (ob->main_stream, note->frequency); | 2411 lto_output_sleb128_stream (ob->main_stream, ii->param_index); |
1978 lto_output_sleb128_stream (ob->main_stream, note->loop_nest); | 2412 lto_output_sleb128_stream (ob->main_stream, ii->anc_offset); |
1979 } | 2413 bp = bitpack_create (); |
1980 | 2414 bp_pack_value (bp, ii->polymorphic, 1); |
1981 /* Read in a parameter call note. */ | 2415 lto_output_bitpack (ob->main_stream, bp); |
1982 | 2416 bitpack_delete (bp); |
1983 static void | 2417 |
1984 ipa_read_param_call_note (struct lto_input_block *ib, | 2418 if (ii->polymorphic) |
1985 struct ipa_node_params *info) | 2419 { |
1986 | 2420 lto_output_sleb128_stream (ob->main_stream, ii->otr_token); |
1987 { | 2421 lto_output_tree (ob, ii->otr_type, true); |
1988 struct ipa_param_call_note *note = XCNEW (struct ipa_param_call_note); | 2422 } |
1989 | 2423 } |
1990 note->lto_stmt_uid = (unsigned int) lto_input_uleb128 (ib); | 2424 |
1991 note->formal_id = (int) lto_input_sleb128 (ib); | 2425 /* Read in parts of cgraph_indirect_call_info corresponding to CS that are |
1992 note->count = (gcov_type) lto_input_sleb128 (ib); | 2426 relevant to indirect inlining from IB. */ |
1993 note->frequency = (int) lto_input_sleb128 (ib); | 2427 |
1994 note->loop_nest = (int) lto_input_sleb128 (ib); | 2428 static void |
1995 | 2429 ipa_read_indirect_edge_info (struct lto_input_block *ib, |
1996 note->next = info->param_calls; | 2430 struct data_in *data_in ATTRIBUTE_UNUSED, |
1997 info->param_calls = note; | 2431 struct cgraph_edge *cs) |
1998 } | 2432 { |
1999 | 2433 struct cgraph_indirect_call_info *ii = cs->indirect_info; |
2434 struct bitpack_d *bp; | |
2435 | |
2436 ii->param_index = (int) lto_input_sleb128 (ib); | |
2437 ii->anc_offset = (HOST_WIDE_INT) lto_input_sleb128 (ib); | |
2438 bp = lto_input_bitpack (ib); | |
2439 ii->polymorphic = bp_unpack_value (bp, 1); | |
2440 bitpack_delete (bp); | |
2441 if (ii->polymorphic) | |
2442 { | |
2443 ii->otr_token = (HOST_WIDE_INT) lto_input_sleb128 (ib); | |
2444 ii->otr_type = lto_input_tree (ib, data_in); | |
2445 } | |
2446 } | |
2000 | 2447 |
2001 /* Stream out NODE info to OB. */ | 2448 /* Stream out NODE info to OB. */ |
2002 | 2449 |
2003 static void | 2450 static void |
2004 ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) | 2451 ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) |
2007 lto_cgraph_encoder_t encoder; | 2454 lto_cgraph_encoder_t encoder; |
2008 struct ipa_node_params *info = IPA_NODE_REF (node); | 2455 struct ipa_node_params *info = IPA_NODE_REF (node); |
2009 int j; | 2456 int j; |
2010 struct cgraph_edge *e; | 2457 struct cgraph_edge *e; |
2011 struct bitpack_d *bp; | 2458 struct bitpack_d *bp; |
2012 int note_count = 0; | |
2013 struct ipa_param_call_note *note; | |
2014 | 2459 |
2015 encoder = ob->decl_state->cgraph_node_encoder; | 2460 encoder = ob->decl_state->cgraph_node_encoder; |
2016 node_ref = lto_cgraph_encoder_encode (encoder, node); | 2461 node_ref = lto_cgraph_encoder_encode (encoder, node); |
2017 lto_output_uleb128_stream (ob->main_stream, node_ref); | 2462 lto_output_uleb128_stream (ob->main_stream, node_ref); |
2018 | 2463 |
2019 bp = bitpack_create (); | 2464 bp = bitpack_create (); |
2020 bp_pack_value (bp, info->called_with_var_arguments, 1); | 2465 bp_pack_value (bp, info->called_with_var_arguments, 1); |
2466 bp_pack_value (bp, info->uses_analysis_done, 1); | |
2021 gcc_assert (info->modification_analysis_done | 2467 gcc_assert (info->modification_analysis_done |
2022 || ipa_get_param_count (info) == 0); | 2468 || 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); | 2469 gcc_assert (!info->node_enqueued); |
2025 gcc_assert (!info->ipcp_orig_node); | 2470 gcc_assert (!info->ipcp_orig_node); |
2026 for (j = 0; j < ipa_get_param_count (info); j++) | 2471 for (j = 0; j < ipa_get_param_count (info); j++) |
2027 { | 2472 { |
2028 bp_pack_value (bp, info->params[j].modified, 1); | 2473 bp_pack_value (bp, info->params[j].modified, 1); |
2029 bp_pack_value (bp, info->params[j].called, 1); | 2474 bp_pack_value (bp, info->params[j].used, 1); |
2030 } | 2475 } |
2031 lto_output_bitpack (ob->main_stream, bp); | 2476 lto_output_bitpack (ob->main_stream, bp); |
2032 bitpack_delete (bp); | 2477 bitpack_delete (bp); |
2033 for (e = node->callees; e; e = e->next_callee) | 2478 for (e = node->callees; e; e = e->next_callee) |
2034 { | 2479 { |
2037 lto_output_uleb128_stream (ob->main_stream, | 2482 lto_output_uleb128_stream (ob->main_stream, |
2038 ipa_get_cs_argument_count (args)); | 2483 ipa_get_cs_argument_count (args)); |
2039 for (j = 0; j < ipa_get_cs_argument_count (args); j++) | 2484 for (j = 0; j < ipa_get_cs_argument_count (args); j++) |
2040 ipa_write_jump_function (ob, ipa_get_ith_jump_func (args, j)); | 2485 ipa_write_jump_function (ob, ipa_get_ith_jump_func (args, j)); |
2041 } | 2486 } |
2042 | 2487 for (e = node->indirect_calls; e; e = e->next_callee) |
2043 for (note = info->param_calls; note; note = note->next) | 2488 ipa_write_indirect_edge_info (ob, e); |
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 } | 2489 } |
2049 | 2490 |
2050 /* Srtream in NODE info from IB. */ | 2491 /* Srtream in NODE info from IB. */ |
2051 | 2492 |
2052 static void | 2493 static void |
2055 { | 2496 { |
2056 struct ipa_node_params *info = IPA_NODE_REF (node); | 2497 struct ipa_node_params *info = IPA_NODE_REF (node); |
2057 int k; | 2498 int k; |
2058 struct cgraph_edge *e; | 2499 struct cgraph_edge *e; |
2059 struct bitpack_d *bp; | 2500 struct bitpack_d *bp; |
2060 int i, note_count; | |
2061 | 2501 |
2062 ipa_initialize_node_params (node); | 2502 ipa_initialize_node_params (node); |
2063 | 2503 |
2064 bp = lto_input_bitpack (ib); | 2504 bp = lto_input_bitpack (ib); |
2065 info->called_with_var_arguments = bp_unpack_value (bp, 1); | 2505 info->called_with_var_arguments = bp_unpack_value (bp, 1); |
2506 info->uses_analysis_done = bp_unpack_value (bp, 1); | |
2066 if (ipa_get_param_count (info) != 0) | 2507 if (ipa_get_param_count (info) != 0) |
2067 { | 2508 { |
2068 info->modification_analysis_done = true; | 2509 info->modification_analysis_done = true; |
2069 info->uses_analysis_done = true; | 2510 info->uses_analysis_done = true; |
2070 } | 2511 } |
2071 info->node_enqueued = false; | 2512 info->node_enqueued = false; |
2072 for (k = 0; k < ipa_get_param_count (info); k++) | 2513 for (k = 0; k < ipa_get_param_count (info); k++) |
2073 { | 2514 { |
2074 info->params[k].modified = bp_unpack_value (bp, 1); | 2515 info->params[k].modified = bp_unpack_value (bp, 1); |
2075 info->params[k].called = bp_unpack_value (bp, 1); | 2516 info->params[k].used = bp_unpack_value (bp, 1); |
2076 } | 2517 } |
2077 bitpack_delete (bp); | 2518 bitpack_delete (bp); |
2078 for (e = node->callees; e; e = e->next_callee) | 2519 for (e = node->callees; e; e = e->next_callee) |
2079 { | 2520 { |
2080 struct ipa_edge_args *args = IPA_EDGE_REF (e); | 2521 struct ipa_edge_args *args = IPA_EDGE_REF (e); |
2087 args->jump_functions = GGC_CNEWVEC (struct ipa_jump_func, | 2528 args->jump_functions = GGC_CNEWVEC (struct ipa_jump_func, |
2088 ipa_get_cs_argument_count (args)); | 2529 ipa_get_cs_argument_count (args)); |
2089 for (k = 0; k < ipa_get_cs_argument_count (args); k++) | 2530 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); | 2531 ipa_read_jump_function (ib, ipa_get_ith_jump_func (args, k), data_in); |
2091 } | 2532 } |
2092 | 2533 for (e = node->indirect_calls; e; e = e->next_callee) |
2093 note_count = lto_input_uleb128 (ib); | 2534 ipa_read_indirect_edge_info (ib, data_in, e); |
2094 for (i = 0; i < note_count; i++) | |
2095 ipa_read_param_call_note (ib, info); | |
2096 } | 2535 } |
2097 | 2536 |
2098 /* Write jump functions for nodes in SET. */ | 2537 /* Write jump functions for nodes in SET. */ |
2099 | 2538 |
2100 void | 2539 void |
2159 lto_cgraph_encoder_t encoder; | 2598 lto_cgraph_encoder_t encoder; |
2160 | 2599 |
2161 index = lto_input_uleb128 (&ib_main); | 2600 index = lto_input_uleb128 (&ib_main); |
2162 encoder = file_data->cgraph_node_encoder; | 2601 encoder = file_data->cgraph_node_encoder; |
2163 node = lto_cgraph_encoder_deref (encoder, index); | 2602 node = lto_cgraph_encoder_deref (encoder, index); |
2603 gcc_assert (node->analyzed); | |
2164 ipa_read_node_info (&ib_main, node, data_in); | 2604 ipa_read_node_info (&ib_main, node, data_in); |
2165 } | 2605 } |
2166 lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, | 2606 lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, |
2167 len); | 2607 len); |
2168 lto_data_in_delete (data_in); | 2608 lto_data_in_delete (data_in); |
2203 | 2643 |
2204 ipa_check_create_node_params (); | 2644 ipa_check_create_node_params (); |
2205 ipa_check_create_edge_args (); | 2645 ipa_check_create_edge_args (); |
2206 | 2646 |
2207 for (node = cgraph_nodes; node; node = node->next) | 2647 for (node = cgraph_nodes; node; node = node->next) |
2208 { | 2648 if (node->analyzed) |
2209 if (!node->analyzed) | |
2210 continue; | |
2211 ipa_initialize_node_params (node); | 2649 ipa_initialize_node_params (node); |
2650 | |
2651 for (node = cgraph_nodes; node; node = node->next) | |
2652 if (node->analyzed) | |
2212 for (cs = node->callees; cs; cs = cs->next_callee) | 2653 for (cs = node->callees; cs; cs = cs->next_callee) |
2213 { | 2654 { |
2214 if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) | 2655 if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) |
2215 != ipa_get_param_count (IPA_NODE_REF (cs->callee))) | 2656 != ipa_get_param_count (IPA_NODE_REF (cs->callee))) |
2216 ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee)); | 2657 ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee)); |
2217 } | 2658 } |
2218 } | 2659 } |
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 } |