1 /* Interprocedural analyses.
2 Copyright (C) 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
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
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
24 #include "langhooks.h"
29 #include "tree-flow.h"
30 #include "tree-pass.h"
31 #include "tree-inline.h"
36 /* Vector where the parameter infos are actually stored. */
37 VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
38 /* Vector where the parameter infos are actually stored. */
39 VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector;
41 /* Holders of ipa cgraph hooks: */
42 struct cgraph_edge_hook_list *edge_removal_hook_holder;
43 struct cgraph_node_hook_list *node_removal_hook_holder;
44 struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
45 struct cgraph_2node_hook_list *node_duplication_hook_holder;
47 /* Initialize worklist to contain all functions. */
48 struct ipa_func_list *
49 ipa_init_func_list (void)
51 struct cgraph_node *node;
52 struct ipa_func_list * wl;
55 for (node = cgraph_nodes; node; node = node->next)
56 ipa_push_func_to_list (&wl, node);
61 /* Add cgraph node MT to the worklist. Set worklist element WL
64 ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *mt)
66 struct ipa_func_list *temp;
68 temp = XCNEW (struct ipa_func_list);
74 /* Remove a function from the worklist. WL points to the first
75 element in the list, which is removed. */
77 ipa_pop_func_from_list (struct ipa_func_list ** wl)
79 struct ipa_func_list *first;
80 struct cgraph_node *return_func;
84 return_func = first->node;
89 /* Return index of the formal whose tree is ptree in function which corresponds
92 ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree)
96 count = ipa_get_param_count (info);
97 for (i = 0; i < count; i++)
98 if (ipa_get_ith_param(info, i) == ptree)
104 /* Insert the formal trees to the param_decls array in function MT. */
106 ipa_create_param_decls_array (struct cgraph_node *mt)
112 struct ipa_node_params *info = IPA_NODE_REF (mt);
114 info->param_decls = XCNEWVEC (tree, ipa_get_param_count (info));
116 fnargs = DECL_ARGUMENTS (fndecl);
118 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
120 info->param_decls[param_num] = parm;
125 /* Count number of formals in MT. Insert the result to the
128 ipa_count_formal_params (struct cgraph_node *mt)
136 fnargs = DECL_ARGUMENTS (fndecl);
138 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
140 ipa_set_param_count (IPA_NODE_REF (mt), param_num);
143 /* Check STMT to detect whether a formal is modified within MT, the appropriate
144 entry is updated in the modified_flags array of ipa_node_params (associated
147 ipa_check_stmt_modifications (struct cgraph_node *mt, tree stmt)
151 struct ipa_node_params *info;
153 switch (TREE_CODE (stmt))
155 case GIMPLE_MODIFY_STMT:
156 if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == PARM_DECL)
158 info = IPA_NODE_REF (mt);
159 parm_decl = GIMPLE_STMT_OPERAND (stmt, 0);
160 index = ipa_get_param_decl_index (info, parm_decl);
162 info->modified_flags[index] = true;
166 /* Asm code could modify any of the parameters. */
167 info = IPA_NODE_REF (mt);
168 for (j = 0; j < ipa_get_param_count (IPA_NODE_REF (mt)); j++)
169 info->modified_flags[j] = true;
176 /* The modify computation driver for MT. Compute which formal arguments
177 of function MT are locally modified. Formals may be modified in MT
178 if their address is taken, or if
179 they appear on the left hand side of an assignment. */
181 ipa_detect_param_modifications (struct cgraph_node *mt)
187 struct function *func;
188 block_stmt_iterator bsi;
189 tree stmt, parm_tree;
190 struct ipa_node_params *info = IPA_NODE_REF (mt);
192 if (ipa_get_param_count (info) == 0 || info->modified_flags)
195 count = ipa_get_param_count (info);
196 info->modified_flags = XCNEWVEC (bool, count);
198 /* ??? Handle pending sizes case. Set all parameters
199 of the function to be modified. */
201 if (DECL_UNINLINABLE (decl))
203 for (j = 0; j < count; j++)
204 info->modified_flags[j] = true;
208 /* Formals whose address is taken are considered modified. */
209 for (j = 0; j < count; j++)
211 parm_tree = ipa_get_ith_param (info, j);
212 if (!is_gimple_reg (parm_tree)
213 && TREE_ADDRESSABLE (parm_tree))
214 info->modified_flags[j] = true;
216 body = DECL_SAVED_TREE (decl);
219 func = DECL_STRUCT_FUNCTION (decl);
220 FOR_EACH_BB_FN (bb, func)
222 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
224 stmt = bsi_stmt (bsi);
225 ipa_check_stmt_modifications (mt, stmt);
231 /* Count number of arguments callsite CS has and store it in
232 ipa_edge_args structure corresponding to this callsite. */
234 ipa_count_arguments (struct cgraph_edge *cs)
239 call_tree = get_call_expr_in (cs->call_stmt);
240 gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
241 arg_num = call_expr_nargs (call_tree);
242 ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num);
245 /* Compute jump function for all arguments of callsite CS
246 and insert the information in the jump_functions array
247 in the ipa_edge_args corresponding to this callsite. */
249 ipa_compute_jump_functions (struct cgraph_edge *cs)
254 struct cgraph_node *mt;
256 struct function *curr_cfun;
257 call_expr_arg_iterator iter;
258 struct ipa_edge_args *args = IPA_EDGE_REF (cs);
260 if (ipa_get_cs_argument_count (args) == 0 || args->jump_functions)
262 args->jump_functions = XCNEWVEC (struct ipa_jump_func,
263 ipa_get_cs_argument_count (args));
264 call_tree = get_call_expr_in (cs->call_stmt);
265 gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
268 FOR_EACH_CALL_EXPR_ARG (arg, iter, call_tree)
270 /* If the formal parameter was passed as argument, we store
271 IPA_PASS_THROUGH and its index in the caller as the jump function
273 if ((TREE_CODE (arg) == SSA_NAME
274 && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
275 || TREE_CODE (arg) == PARM_DECL)
277 struct ipa_node_params *info;
281 info = IPA_NODE_REF (mt);
282 parm_decl = TREE_CODE (arg) == PARM_DECL ? arg : SSA_NAME_VAR (arg);
284 index = ipa_get_param_decl_index (info, parm_decl);
285 if (TREE_CODE (arg) == SSA_NAME && IS_VALID_JUMP_FUNC_INDEX (index))
287 curr_cfun = DECL_STRUCT_FUNCTION (mt->decl);
288 if (!gimple_default_def (curr_cfun, parm_decl)
289 || gimple_default_def (curr_cfun, parm_decl) != arg)
290 info->modified_flags[index] = true;
292 if (!IS_VALID_JUMP_FUNC_INDEX (index) || info->modified_flags[index])
293 args->jump_functions[arg_num].type = IPA_UNKNOWN;
296 args->jump_functions[arg_num].type = IPA_PASS_THROUGH;
297 args->jump_functions[arg_num].value.formal_id = index;
300 /* If a constant value was passed as argument,
301 we store IPA_CONST and its value as the jump function
303 else if (TREE_CODE (arg) == INTEGER_CST
304 || TREE_CODE (arg) == REAL_CST
305 || TREE_CODE (arg) == FIXED_CST)
307 args->jump_functions[arg_num].type = IPA_CONST;
308 args->jump_functions[arg_num].value.constant = arg;
310 /* This is for the case of Fortran. If the address of a const_decl
311 was passed as argument then we store
312 IPA_CONST_REF/IPA_CONST_REF and the constant
313 value as the jump function corresponding to this argument. */
314 else if (TREE_CODE (arg) == ADDR_EXPR
315 && TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL)
317 cst_decl = TREE_OPERAND (arg, 0);
318 if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST
319 || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST
320 || TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST)
322 args->jump_functions[arg_num].type = IPA_CONST_REF;
323 args->jump_functions[arg_num].value.constant = cst_decl;
327 args->jump_functions[arg_num].type = IPA_UNKNOWN;
332 /* Frees all dynamically allocated structures that the argument info points
335 ipa_free_edge_args_substructures (struct ipa_edge_args *args)
337 if (args->jump_functions)
338 free (args->jump_functions);
340 memset (args, 0, sizeof (*args));
343 /* Free all ipa_edge structures. */
345 ipa_free_all_edge_args (void)
348 struct ipa_edge_args *args;
351 VEC_iterate (ipa_edge_args_t, ipa_edge_args_vector, i, args);
353 ipa_free_edge_args_substructures (args);
355 VEC_free (ipa_edge_args_t, heap, ipa_edge_args_vector);
356 ipa_edge_args_vector = NULL;
359 /* Frees all dynamically allocated structures that the param info points
362 ipa_free_node_params_substructures (struct ipa_node_params *info)
364 if (info->ipcp_lattices)
365 free (info->ipcp_lattices);
366 if (info->param_decls)
367 free (info->param_decls);
368 if (info->modified_flags)
369 free (info->modified_flags);
371 memset (info, 0, sizeof (*info));
374 /* Free all ipa_node_params structures. */
376 ipa_free_all_node_params (void)
379 struct ipa_node_params *info;
382 VEC_iterate (ipa_node_params_t, ipa_node_params_vector, i, info);
384 ipa_free_node_params_substructures (info);
386 VEC_free (ipa_node_params_t, heap, ipa_node_params_vector);
387 ipa_node_params_vector = NULL;
390 /* Hook that is called by cgraph.c when an edge is removed. */
392 ipa_edge_removal_hook (struct cgraph_edge *cs,
393 void *data __attribute__ ((unused)))
395 ipa_free_edge_args_substructures (IPA_EDGE_REF (cs));
398 /* Hook that is called by cgraph.c when a node is removed. */
400 ipa_node_removal_hook (struct cgraph_node *node,
401 void *data __attribute__ ((unused)))
403 ipa_free_node_params_substructures (IPA_NODE_REF (node));
406 /* Helper function to duplicate an array of size N that is at SRC and store a
407 pointer to it to DST. Nothing is done if SRC is NULL. */
409 duplicate_array (void *src, size_t n)
421 /* Hook that is called by cgraph.c when a node is duplicated. */
423 ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
426 struct ipa_edge_args *old_args, *new_args;
429 ipa_check_create_edge_args ();
431 old_args = IPA_EDGE_REF (src);
432 new_args = IPA_EDGE_REF (dst);
434 arg_count = ipa_get_cs_argument_count (old_args);
435 ipa_set_cs_argument_count (new_args, arg_count);
436 new_args->jump_functions = (struct ipa_jump_func *)
437 duplicate_array (old_args->jump_functions,
438 sizeof (struct ipa_jump_func) * arg_count);
439 data = data; /* Suppressing compiler warning. */
442 /* Hook that is called by cgraph.c when a node is duplicated. */
444 ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
447 struct ipa_node_params *old_info, *new_info;
450 ipa_check_create_node_params ();
451 old_info = IPA_NODE_REF (src);
452 new_info = IPA_NODE_REF (dst);
453 param_count = ipa_get_param_count (old_info);
455 ipa_set_param_count (new_info, param_count);
456 new_info->ipcp_lattices = (struct ipcp_lattice *)
457 duplicate_array (old_info->ipcp_lattices,
458 sizeof (struct ipcp_lattice) * param_count);
459 new_info->param_decls = (tree *)
460 duplicate_array (old_info->param_decls, sizeof (tree) * param_count);
461 new_info->modified_flags = (bool *)
462 duplicate_array (old_info->modified_flags, sizeof (bool) * param_count);
464 new_info->ipcp_orig_node = old_info->ipcp_orig_node;
465 new_info->count_scale = old_info->count_scale;
467 data = data; /* Suppressing compiler warning. */
470 /* Register our cgraph hooks if they are not already there. */
472 ipa_register_cgraph_hooks (void)
474 if (!edge_removal_hook_holder)
475 edge_removal_hook_holder =
476 cgraph_add_edge_removal_hook (&ipa_edge_removal_hook, NULL);
477 if (!node_removal_hook_holder)
478 node_removal_hook_holder =
479 cgraph_add_node_removal_hook (&ipa_node_removal_hook, NULL);
480 if (!edge_duplication_hook_holder)
481 edge_duplication_hook_holder =
482 cgraph_add_edge_duplication_hook (&ipa_edge_duplication_hook, NULL);
483 if (!node_duplication_hook_holder)
484 node_duplication_hook_holder =
485 cgraph_add_node_duplication_hook (&ipa_node_duplication_hook, NULL);
488 /* Unregister our cgraph hooks if they are not already there. */
490 ipa_unregister_cgraph_hooks (void)
492 cgraph_remove_edge_removal_hook (edge_removal_hook_holder);
493 edge_removal_hook_holder = NULL;
494 cgraph_remove_node_removal_hook (node_removal_hook_holder);
495 node_removal_hook_holder = NULL;
496 cgraph_remove_edge_duplication_hook (edge_duplication_hook_holder);
497 edge_duplication_hook_holder = NULL;
498 cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
499 node_duplication_hook_holder = NULL;
502 /* Free all ipa_node_params and all ipa_edge_args structures if they are no
503 longer needed after ipa-cp. */
505 free_all_ipa_structures_after_ipa_cp (void)
507 ipa_free_all_edge_args ();
508 ipa_free_all_node_params ();
509 ipa_unregister_cgraph_hooks ();
512 /* Print ipa_tree_map data structures of all functions in the
515 ipa_print_all_tree_maps (FILE * f)
519 struct cgraph_node *node;
521 fprintf (f, "\nPARAM TREE MAP PRINT\n");
522 for (node = cgraph_nodes; node; node = node->next)
524 struct ipa_node_params *info = IPA_NODE_REF (node);
525 fprintf (f, "function %s Trees :: \n", cgraph_node_name (node));
526 count = ipa_get_param_count (info);
527 for (i = 0; i < count; i++)
529 temp = ipa_get_ith_param (info, i);
530 if (TREE_CODE (temp) == PARM_DECL)
531 fprintf (f, " param [%d] : %s\n", i,
532 (*lang_hooks.decl_printable_name) (temp, 2));
538 /* Print modified_flags data structures of all functions in the
541 ipa_print_all_params_modified (FILE * f)
545 struct cgraph_node *node;
547 fprintf (f, "\nMODIFY PRINT\n");
548 for (node = cgraph_nodes; node; node = node->next)
550 struct ipa_node_params *info = IPA_NODE_REF (node);
551 fprintf (f, "function %s :: \n", cgraph_node_name (node));
552 count = ipa_get_param_count (info);
553 for (i = 0; i < count; i++)
555 temp = info->modified_flags[i];
557 fprintf (f, " param [%d] true \n", i);
559 fprintf (f, " param [%d] false \n", i);