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"
34 /* Initialize worklist to contain all functions. */
35 struct ipa_func_list
*
36 ipa_init_func_list (void)
38 struct cgraph_node
*node
;
39 struct ipa_func_list
* wl
;
42 for (node
= cgraph_nodes
; node
; node
= node
->next
)
43 ipa_push_func_to_list (&wl
, node
);
48 /* Add cgraph node MT to the worklist. Set worklist element WL
51 ipa_push_func_to_list (struct ipa_func_list
**wl
, struct cgraph_node
*mt
)
53 struct ipa_func_list
*temp
;
55 temp
= xcalloc (1, sizeof (struct ipa_func_list
));
61 /* Remove a function from the worklist. WL points to the first
62 element in the list, which is removed. */
64 ipa_pop_func_from_list (struct ipa_func_list
** wl
)
66 struct ipa_func_list
*first
;
67 struct cgraph_node
*return_func
;
71 return_func
= first
->node
;
76 /* Return index of the formal whose tree is ptree in function which corresponds
79 ipa_get_param_decl_index (struct ipa_node_params
*info
, tree ptree
)
83 count
= ipa_get_param_count (info
);
84 for (i
= 0; i
< count
; i
++)
85 if (ipa_get_ith_param(info
, i
) == ptree
)
91 /* Insert the formal trees to the param_decls array in function MT. */
93 ipa_create_param_decls_array (struct cgraph_node
*mt
)
99 struct ipa_node_params
*info
= IPA_NODE_REF (mt
);
101 info
->param_decls
= XCNEWVEC (tree
, ipa_get_param_count (info
));
103 fnargs
= DECL_ARGUMENTS (fndecl
);
105 for (parm
= fnargs
; parm
; parm
= TREE_CHAIN (parm
))
107 info
->param_decls
[param_num
] = parm
;
112 /* Count number of formals in MT. Insert the result to the
115 ipa_count_formal_params (struct cgraph_node
*mt
)
123 fnargs
= DECL_ARGUMENTS (fndecl
);
125 for (parm
= fnargs
; parm
; parm
= TREE_CHAIN (parm
))
127 ipa_set_param_count (IPA_NODE_REF (mt
), param_num
);
130 /* Check STMT to detect whether a formal is modified within MT, the appropriate
131 entry is updated in the modified_flags array of ipa_node_params (associated
134 ipa_check_stmt_modifications (struct cgraph_node
*mt
, tree stmt
)
138 struct ipa_node_params
*info
;
140 switch (TREE_CODE (stmt
))
142 case GIMPLE_MODIFY_STMT
:
143 if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt
, 0)) == PARM_DECL
)
145 info
= IPA_NODE_REF (mt
);
146 parm_decl
= GIMPLE_STMT_OPERAND (stmt
, 0);
147 index
= ipa_get_param_decl_index (info
, parm_decl
);
149 info
->modified_flags
[index
] = true;
153 /* Asm code could modify any of the parameters. */
154 info
= IPA_NODE_REF (mt
);
155 for (j
= 0; j
< ipa_get_param_count (IPA_NODE_REF (mt
)); j
++)
156 info
->modified_flags
[j
] = true;
163 /* The modify computation driver for MT. Compute which formal arguments
164 of function MT are locally modified. Formals may be modified in MT
165 if their address is taken, or if
166 they appear on the left hand side of an assignment. */
168 ipa_detect_param_modifications (struct cgraph_node
*mt
)
174 struct function
*func
;
175 block_stmt_iterator bsi
;
176 tree stmt
, parm_tree
;
177 struct ipa_node_params
*info
= IPA_NODE_REF (mt
);
179 if (ipa_get_param_count (info
) == 0)
182 count
= ipa_get_param_count (info
);
183 info
->modified_flags
= XCNEWVEC (bool, count
);
185 /* ??? Handle pending sizes case. Set all parameters
186 of the function to be modified. */
188 if (DECL_UNINLINABLE (decl
))
190 for (j
= 0; j
< count
; j
++)
191 info
->modified_flags
[j
] = true;
195 /* Formals whose address is taken are considered modified. */
196 for (j
= 0; j
< count
; j
++)
198 parm_tree
= ipa_get_ith_param (info
, j
);
199 if (!is_gimple_reg (parm_tree
)
200 && TREE_ADDRESSABLE (parm_tree
))
201 info
->modified_flags
[j
] = true;
203 body
= DECL_SAVED_TREE (decl
);
206 func
= DECL_STRUCT_FUNCTION (decl
);
207 FOR_EACH_BB_FN (bb
, func
)
209 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
211 stmt
= bsi_stmt (bsi
);
212 ipa_check_stmt_modifications (mt
, stmt
);
218 /* Count number of arguments callsite CS has and store it in
219 ipa_edge_args structure corresponding to this callsite. */
221 ipa_count_arguments (struct cgraph_edge
*cs
)
226 call_tree
= get_call_expr_in (cs
->call_stmt
);
227 gcc_assert (TREE_CODE (call_tree
) == CALL_EXPR
);
228 arg_num
= call_expr_nargs (call_tree
);
229 ipa_set_cs_argument_count (IPA_EDGE_REF (cs
), arg_num
);
232 /* Compute jump function for all arguments of callsite CS
233 and insert the information in the jump_functions array
234 in the ipa_edge_args corresponding to this callsite. */
236 ipa_compute_jump_functions (struct cgraph_edge
*cs
)
241 struct cgraph_node
*mt
;
243 struct function
*curr_cfun
;
244 call_expr_arg_iterator iter
;
245 struct ipa_edge_args
*args
= IPA_EDGE_REF (cs
);
247 if (ipa_get_cs_argument_count (args
) == 0)
249 args
->jump_functions
= XCNEWVEC (struct ipa_jump_func
,
250 ipa_get_cs_argument_count (args
));
251 call_tree
= get_call_expr_in (cs
->call_stmt
);
252 gcc_assert (TREE_CODE (call_tree
) == CALL_EXPR
);
255 FOR_EACH_CALL_EXPR_ARG (arg
, iter
, call_tree
)
257 /* If the formal parameter was passed as argument, we store
258 IPA_PASS_THROUGH and its index in the caller as the jump function
260 if ((TREE_CODE (arg
) == SSA_NAME
261 && TREE_CODE (SSA_NAME_VAR (arg
)) == PARM_DECL
)
262 || TREE_CODE (arg
) == PARM_DECL
)
264 struct ipa_node_params
*info
;
268 info
= IPA_NODE_REF (mt
);
269 parm_decl
= TREE_CODE (arg
) == PARM_DECL
? arg
: SSA_NAME_VAR (arg
);
271 index
= ipa_get_param_decl_index (info
, parm_decl
);
272 if (TREE_CODE (arg
) == SSA_NAME
&& IS_VALID_JUMP_FUNC_INDEX (index
))
274 curr_cfun
= DECL_STRUCT_FUNCTION (mt
->decl
);
275 if (!gimple_default_def (curr_cfun
, parm_decl
)
276 || gimple_default_def (curr_cfun
, parm_decl
) != arg
)
277 info
->modified_flags
[index
] = true;
279 if (!IS_VALID_JUMP_FUNC_INDEX (index
) || info
->modified_flags
[index
])
280 args
->jump_functions
[arg_num
].type
= IPA_UNKNOWN
;
283 args
->jump_functions
[arg_num
].type
= IPA_PASS_THROUGH
;
284 args
->jump_functions
[arg_num
].value
.formal_id
= index
;
287 /* If a constant value was passed as argument,
288 we store IPA_CONST and its value as the jump function
290 else if (TREE_CODE (arg
) == INTEGER_CST
291 || TREE_CODE (arg
) == REAL_CST
292 || TREE_CODE (arg
) == FIXED_CST
)
294 args
->jump_functions
[arg_num
].type
= IPA_CONST
;
295 args
->jump_functions
[arg_num
].value
.constant
= arg
;
297 /* This is for the case of Fortran. If the address of a const_decl
298 was passed as argument then we store
299 IPA_CONST_REF/IPA_CONST_REF and the constant
300 value as the jump function corresponding to this argument. */
301 else if (TREE_CODE (arg
) == ADDR_EXPR
302 && TREE_CODE (TREE_OPERAND (arg
, 0)) == CONST_DECL
)
304 cst_decl
= TREE_OPERAND (arg
, 0);
305 if (TREE_CODE (DECL_INITIAL (cst_decl
)) == INTEGER_CST
306 || TREE_CODE (DECL_INITIAL (cst_decl
)) == REAL_CST
307 || TREE_CODE (DECL_INITIAL (cst_decl
)) == FIXED_CST
)
309 args
->jump_functions
[arg_num
].type
= IPA_CONST_REF
;
310 args
->jump_functions
[arg_num
].value
.constant
= cst_decl
;
314 args
->jump_functions
[arg_num
].type
= IPA_UNKNOWN
;
319 /* Allocate and initialize ipa_node_params structure for the given cgraph
322 ipa_create_node_params (struct cgraph_node
*node
)
324 node
->aux
= xcalloc (1, sizeof (struct ipa_node_params
));
327 /* Allocate and initialize ipa_node_params structure for all
328 nodes in callgraph. */
330 ipa_create_all_node_params (void)
332 struct cgraph_node
*node
;
334 for (node
= cgraph_nodes
; node
; node
= node
->next
)
335 ipa_create_node_params (node
);
338 /* Allocate and initialize ipa_edge structure. */
340 ipa_create_all_edge_args (void)
342 struct cgraph_node
*node
;
343 struct cgraph_edge
*cs
;
345 for (node
= cgraph_nodes
; node
; node
= node
->next
)
346 for (cs
= node
->callees
; cs
; cs
= cs
->next_callee
)
347 cs
->aux
= xcalloc (1, sizeof (struct ipa_edge_args
));
350 /* Free ipa_edge structure. */
352 ipa_free_all_edge_args (void)
354 struct cgraph_node
*node
;
355 struct cgraph_edge
*cs
;
357 for (node
= cgraph_nodes
; node
; node
= node
->next
)
358 for (cs
= node
->callees
; cs
; cs
= cs
->next_callee
)
361 if (IPA_EDGE_REF (cs
)->jump_functions
)
362 free (IPA_EDGE_REF (cs
)->jump_functions
);
368 /* Free ipa data structures of ipa_node_params and ipa_edge_args. */
370 ipa_free_all_node_params (void)
372 struct cgraph_node
*node
;
374 for (node
= cgraph_nodes
; node
; node
= node
->next
)
376 if (node
->aux
== NULL
)
378 if (IPA_NODE_REF (node
)->ipcp_lattices
)
379 free (IPA_NODE_REF (node
)->ipcp_lattices
);
380 if (IPA_NODE_REF (node
)->param_decls
)
381 free (IPA_NODE_REF (node
)->param_decls
);
382 if (IPA_NODE_REF (node
)->modified_flags
)
383 free (IPA_NODE_REF (node
)->modified_flags
);
389 /* Print ipa_tree_map data structures of all functions in the
392 ipa_print_all_tree_maps (FILE * f
)
396 struct cgraph_node
*node
;
398 fprintf (f
, "\nPARAM TREE MAP PRINT\n");
399 for (node
= cgraph_nodes
; node
; node
= node
->next
)
401 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
402 fprintf (f
, "function %s Trees :: \n", cgraph_node_name (node
));
403 count
= ipa_get_param_count (info
);
404 for (i
= 0; i
< count
; i
++)
406 temp
= ipa_get_ith_param (info
, i
);
407 if (TREE_CODE (temp
) == PARM_DECL
)
408 fprintf (f
, " param [%d] : %s\n", i
,
409 (*lang_hooks
.decl_printable_name
) (temp
, 2));
415 /* Print modified_flags data structures of all functions in the
418 ipa_print_all_params_modified (FILE * f
)
422 struct cgraph_node
*node
;
424 fprintf (f
, "\nMODIFY PRINT\n");
425 for (node
= cgraph_nodes
; node
; node
= node
->next
)
427 struct ipa_node_params
*info
= IPA_NODE_REF (node
);
428 fprintf (f
, "function %s :: \n", cgraph_node_name (node
));
429 count
= ipa_get_param_count (info
);
430 for (i
= 0; i
< count
; i
++)
432 temp
= info
->modified_flags
[i
];
434 fprintf (f
, " param [%d] true \n", i
);
436 fprintf (f
, " param [%d] false \n", i
);