]>
Commit | Line | Data |
---|---|---|
518dc859 | 1 | /* Interprocedural analyses. |
9dcd6f09 | 2 | Copyright (C) 2005, 2007 Free Software Foundation, Inc. |
518dc859 RL |
3 | |
4 | This file is part of GCC. | |
5 | ||
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 | |
9dcd6f09 | 8 | Software Foundation; either version 3, or (at your option) any later |
518dc859 RL |
9 | version. |
10 | ||
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 | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
518dc859 RL |
19 | |
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "tree.h" | |
24 | #include "langhooks.h" | |
25 | #include "ggc.h" | |
26 | #include "target.h" | |
27 | #include "cgraph.h" | |
28 | #include "ipa-prop.h" | |
29 | #include "tree-flow.h" | |
30 | #include "tree-pass.h" | |
31 | #include "flags.h" | |
32 | #include "timevar.h" | |
33 | ||
dcd416e3 MJ |
34 | /* Initialize worklist to contain all functions. */ |
35 | struct ipa_func_list * | |
36 | ipa_init_func_list (void) | |
518dc859 RL |
37 | { |
38 | struct cgraph_node *node; | |
dcd416e3 | 39 | struct ipa_func_list * wl; |
518dc859 RL |
40 | |
41 | wl = NULL; | |
42 | for (node = cgraph_nodes; node; node = node->next) | |
dcd416e3 | 43 | ipa_push_func_to_list (&wl, node); |
518dc859 RL |
44 | |
45 | return wl; | |
46 | } | |
47 | ||
dcd416e3 | 48 | /* Add cgraph node MT to the worklist. Set worklist element WL |
518dc859 RL |
49 | to point to MT. */ |
50 | void | |
dcd416e3 | 51 | ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *mt) |
518dc859 | 52 | { |
dcd416e3 | 53 | struct ipa_func_list *temp; |
518dc859 | 54 | |
d3bfe4de | 55 | temp = XCNEW (struct ipa_func_list); |
dcd416e3 MJ |
56 | temp->node = mt; |
57 | temp->next = *wl; | |
518dc859 RL |
58 | *wl = temp; |
59 | } | |
60 | ||
dcd416e3 | 61 | /* Remove a function from the worklist. WL points to the first |
518dc859 RL |
62 | element in the list, which is removed. */ |
63 | struct cgraph_node * | |
dcd416e3 | 64 | ipa_pop_func_from_list (struct ipa_func_list ** wl) |
518dc859 | 65 | { |
dcd416e3 MJ |
66 | struct ipa_func_list *first; |
67 | struct cgraph_node *return_func; | |
518dc859 RL |
68 | |
69 | first = *wl; | |
dcd416e3 MJ |
70 | *wl = (*wl)->next; |
71 | return_func = first->node; | |
518dc859 | 72 | free (first); |
dcd416e3 | 73 | return return_func; |
518dc859 RL |
74 | } |
75 | ||
dcd416e3 MJ |
76 | /* Return index of the formal whose tree is ptree in function which corresponds |
77 | to info. */ | |
518dc859 | 78 | static int |
dcd416e3 | 79 | ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree) |
518dc859 RL |
80 | { |
81 | int i, count; | |
82 | ||
dcd416e3 | 83 | count = ipa_get_param_count (info); |
518dc859 | 84 | for (i = 0; i < count; i++) |
dcd416e3 | 85 | if (ipa_get_ith_param(info, i) == ptree) |
518dc859 RL |
86 | return i; |
87 | ||
88 | return -1; | |
89 | } | |
90 | ||
dcd416e3 | 91 | /* Insert the formal trees to the param_decls array in function MT. */ |
518dc859 | 92 | void |
dcd416e3 | 93 | ipa_create_param_decls_array (struct cgraph_node *mt) |
518dc859 RL |
94 | { |
95 | tree fndecl; | |
96 | tree fnargs; | |
97 | tree parm; | |
98 | int param_num; | |
dcd416e3 | 99 | struct ipa_node_params *info = IPA_NODE_REF (mt); |
518dc859 | 100 | |
dcd416e3 | 101 | info->param_decls = XCNEWVEC (tree, ipa_get_param_count (info)); |
518dc859 RL |
102 | fndecl = mt->decl; |
103 | fnargs = DECL_ARGUMENTS (fndecl); | |
104 | param_num = 0; | |
105 | for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) | |
106 | { | |
dcd416e3 | 107 | info->param_decls[param_num] = parm; |
518dc859 RL |
108 | param_num++; |
109 | } | |
110 | } | |
111 | ||
112 | /* Count number of formals in MT. Insert the result to the | |
dcd416e3 | 113 | ipa_node_params. */ |
518dc859 | 114 | void |
dcd416e3 | 115 | ipa_count_formal_params (struct cgraph_node *mt) |
518dc859 RL |
116 | { |
117 | tree fndecl; | |
118 | tree fnargs; | |
119 | tree parm; | |
120 | int param_num; | |
121 | ||
122 | fndecl = mt->decl; | |
123 | fnargs = DECL_ARGUMENTS (fndecl); | |
124 | param_num = 0; | |
125 | for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) | |
126 | param_num++; | |
dcd416e3 | 127 | ipa_set_param_count (IPA_NODE_REF (mt), param_num); |
518dc859 RL |
128 | } |
129 | ||
dcd416e3 MJ |
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 | |
132 | with MT). */ | |
518dc859 | 133 | static void |
dcd416e3 | 134 | ipa_check_stmt_modifications (struct cgraph_node *mt, tree stmt) |
518dc859 | 135 | { |
dcd416e3 | 136 | int index, j; |
3cc1cccc | 137 | tree parm_decl; |
dcd416e3 | 138 | struct ipa_node_params *info; |
518dc859 RL |
139 | |
140 | switch (TREE_CODE (stmt)) | |
141 | { | |
07beea0d | 142 | case GIMPLE_MODIFY_STMT: |
3cc1cccc | 143 | if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == PARM_DECL) |
518dc859 | 144 | { |
dcd416e3 | 145 | info = IPA_NODE_REF (mt); |
3cc1cccc | 146 | parm_decl = GIMPLE_STMT_OPERAND (stmt, 0); |
dcd416e3 MJ |
147 | index = ipa_get_param_decl_index (info, parm_decl); |
148 | if (index >= 0) | |
149 | info->modified_flags[index] = true; | |
518dc859 RL |
150 | } |
151 | break; | |
152 | case ASM_EXPR: | |
153 | /* Asm code could modify any of the parameters. */ | |
dcd416e3 MJ |
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; | |
518dc859 RL |
157 | break; |
158 | default: | |
159 | break; | |
160 | } | |
161 | } | |
162 | ||
518dc859 | 163 | /* The modify computation driver for MT. Compute which formal arguments |
dcd416e3 | 164 | of function MT are locally modified. Formals may be modified in MT |
518dc859 RL |
165 | if their address is taken, or if |
166 | they appear on the left hand side of an assignment. */ | |
167 | void | |
dcd416e3 | 168 | ipa_detect_param_modifications (struct cgraph_node *mt) |
518dc859 RL |
169 | { |
170 | tree decl; | |
171 | tree body; | |
172 | int j, count; | |
173 | basic_block bb; | |
174 | struct function *func; | |
175 | block_stmt_iterator bsi; | |
176 | tree stmt, parm_tree; | |
dcd416e3 | 177 | struct ipa_node_params *info = IPA_NODE_REF (mt); |
518dc859 | 178 | |
dcd416e3 | 179 | if (ipa_get_param_count (info) == 0) |
3cc1cccc RL |
180 | return; |
181 | ||
dcd416e3 MJ |
182 | count = ipa_get_param_count (info); |
183 | info->modified_flags = XCNEWVEC (bool, count); | |
518dc859 | 184 | decl = mt->decl; |
518dc859 | 185 | /* ??? Handle pending sizes case. Set all parameters |
dcd416e3 | 186 | of the function to be modified. */ |
3cc1cccc | 187 | |
518dc859 RL |
188 | if (DECL_UNINLINABLE (decl)) |
189 | { | |
190 | for (j = 0; j < count; j++) | |
dcd416e3 MJ |
191 | info->modified_flags[j] = true; |
192 | ||
518dc859 RL |
193 | return; |
194 | } | |
195 | /* Formals whose address is taken are considered modified. */ | |
196 | for (j = 0; j < count; j++) | |
197 | { | |
dcd416e3 | 198 | parm_tree = ipa_get_ith_param (info, j); |
3cc1cccc RL |
199 | if (!is_gimple_reg (parm_tree) |
200 | && TREE_ADDRESSABLE (parm_tree)) | |
dcd416e3 | 201 | info->modified_flags[j] = true; |
518dc859 RL |
202 | } |
203 | body = DECL_SAVED_TREE (decl); | |
204 | if (body != NULL) | |
205 | { | |
206 | func = DECL_STRUCT_FUNCTION (decl); | |
207 | FOR_EACH_BB_FN (bb, func) | |
208 | { | |
209 | for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) | |
210 | { | |
211 | stmt = bsi_stmt (bsi); | |
dcd416e3 | 212 | ipa_check_stmt_modifications (mt, stmt); |
518dc859 RL |
213 | } |
214 | } | |
215 | } | |
216 | } | |
217 | ||
518dc859 | 218 | /* Count number of arguments callsite CS has and store it in |
dcd416e3 | 219 | ipa_edge_args structure corresponding to this callsite. */ |
518dc859 | 220 | void |
dcd416e3 | 221 | ipa_count_arguments (struct cgraph_edge *cs) |
518dc859 RL |
222 | { |
223 | tree call_tree; | |
518dc859 RL |
224 | int arg_num; |
225 | ||
dcd416e3 | 226 | call_tree = get_call_expr_in (cs->call_stmt); |
518dc859 | 227 | gcc_assert (TREE_CODE (call_tree) == CALL_EXPR); |
5039610b | 228 | arg_num = call_expr_nargs (call_tree); |
dcd416e3 | 229 | ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num); |
518dc859 RL |
230 | } |
231 | ||
232 | /* Compute jump function for all arguments of callsite CS | |
dcd416e3 MJ |
233 | and insert the information in the jump_functions array |
234 | in the ipa_edge_args corresponding to this callsite. */ | |
518dc859 | 235 | void |
dcd416e3 | 236 | ipa_compute_jump_functions (struct cgraph_edge *cs) |
518dc859 RL |
237 | { |
238 | tree call_tree; | |
a8bd670c | 239 | tree arg, cst_decl; |
518dc859 | 240 | int arg_num; |
518dc859 | 241 | struct cgraph_node *mt; |
3cc1cccc RL |
242 | tree parm_decl; |
243 | struct function *curr_cfun; | |
5039610b | 244 | call_expr_arg_iterator iter; |
dcd416e3 | 245 | struct ipa_edge_args *args = IPA_EDGE_REF (cs); |
518dc859 | 246 | |
dcd416e3 | 247 | if (ipa_get_cs_argument_count (args) == 0) |
518dc859 | 248 | return; |
dcd416e3 MJ |
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); | |
518dc859 | 252 | gcc_assert (TREE_CODE (call_tree) == CALL_EXPR); |
518dc859 RL |
253 | arg_num = 0; |
254 | ||
5039610b | 255 | FOR_EACH_CALL_EXPR_ARG (arg, iter, call_tree) |
518dc859 RL |
256 | { |
257 | /* If the formal parameter was passed as argument, we store | |
dcd416e3 | 258 | IPA_PASS_THROUGH and its index in the caller as the jump function |
518dc859 | 259 | of this argument. */ |
5039610b SL |
260 | if ((TREE_CODE (arg) == SSA_NAME |
261 | && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL) | |
262 | || TREE_CODE (arg) == PARM_DECL) | |
518dc859 | 263 | { |
dcd416e3 MJ |
264 | struct ipa_node_params *info; |
265 | int index; | |
266 | ||
267 | mt = cs->caller; | |
268 | info = IPA_NODE_REF (mt); | |
5039610b | 269 | parm_decl = TREE_CODE (arg) == PARM_DECL ? arg : SSA_NAME_VAR (arg); |
3cc1cccc | 270 | |
dcd416e3 MJ |
271 | index = ipa_get_param_decl_index (info, parm_decl); |
272 | if (TREE_CODE (arg) == SSA_NAME && IS_VALID_JUMP_FUNC_INDEX (index)) | |
3cc1cccc | 273 | { |
5039610b | 274 | curr_cfun = DECL_STRUCT_FUNCTION (mt->decl); |
3cc1cccc | 275 | if (!gimple_default_def (curr_cfun, parm_decl) |
5039610b | 276 | || gimple_default_def (curr_cfun, parm_decl) != arg) |
dcd416e3 | 277 | info->modified_flags[index] = true; |
5039610b | 278 | } |
dcd416e3 MJ |
279 | if (!IS_VALID_JUMP_FUNC_INDEX (index) || info->modified_flags[index]) |
280 | args->jump_functions[arg_num].type = IPA_UNKNOWN; | |
518dc859 RL |
281 | else |
282 | { | |
dcd416e3 MJ |
283 | args->jump_functions[arg_num].type = IPA_PASS_THROUGH; |
284 | args->jump_functions[arg_num].value.formal_id = index; | |
518dc859 RL |
285 | } |
286 | } | |
287 | /* If a constant value was passed as argument, | |
dcd416e3 | 288 | we store IPA_CONST and its value as the jump function |
518dc859 | 289 | of this argument. */ |
5039610b | 290 | else if (TREE_CODE (arg) == INTEGER_CST |
325217ed CF |
291 | || TREE_CODE (arg) == REAL_CST |
292 | || TREE_CODE (arg) == FIXED_CST) | |
518dc859 | 293 | { |
dcd416e3 MJ |
294 | args->jump_functions[arg_num].type = IPA_CONST; |
295 | args->jump_functions[arg_num].value.constant = arg; | |
518dc859 RL |
296 | } |
297 | /* This is for the case of Fortran. If the address of a const_decl | |
dcd416e3 MJ |
298 | was passed as argument then we store |
299 | IPA_CONST_REF/IPA_CONST_REF and the constant | |
518dc859 | 300 | value as the jump function corresponding to this argument. */ |
5039610b SL |
301 | else if (TREE_CODE (arg) == ADDR_EXPR |
302 | && TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL) | |
518dc859 | 303 | { |
5039610b | 304 | cst_decl = TREE_OPERAND (arg, 0); |
518dc859 | 305 | if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST |
325217ed CF |
306 | || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST |
307 | || TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST) | |
518dc859 | 308 | { |
dcd416e3 MJ |
309 | args->jump_functions[arg_num].type = IPA_CONST_REF; |
310 | args->jump_functions[arg_num].value.constant = cst_decl; | |
518dc859 RL |
311 | } |
312 | } | |
313 | else | |
dcd416e3 | 314 | args->jump_functions[arg_num].type = IPA_UNKNOWN; |
518dc859 RL |
315 | arg_num++; |
316 | } | |
317 | } | |
318 | ||
dcd416e3 MJ |
319 | /* Allocate and initialize ipa_node_params structure for the given cgraph |
320 | node. */ | |
518dc859 | 321 | void |
dcd416e3 | 322 | ipa_create_node_params (struct cgraph_node *node) |
518dc859 | 323 | { |
dcd416e3 | 324 | node->aux = xcalloc (1, sizeof (struct ipa_node_params)); |
518dc859 RL |
325 | } |
326 | ||
dcd416e3 | 327 | /* Allocate and initialize ipa_node_params structure for all |
518dc859 RL |
328 | nodes in callgraph. */ |
329 | void | |
dcd416e3 | 330 | ipa_create_all_node_params (void) |
518dc859 RL |
331 | { |
332 | struct cgraph_node *node; | |
333 | ||
334 | for (node = cgraph_nodes; node; node = node->next) | |
dcd416e3 | 335 | ipa_create_node_params (node); |
518dc859 RL |
336 | } |
337 | ||
338 | /* Allocate and initialize ipa_edge structure. */ | |
339 | void | |
dcd416e3 | 340 | ipa_create_all_edge_args (void) |
518dc859 RL |
341 | { |
342 | struct cgraph_node *node; | |
343 | struct cgraph_edge *cs; | |
344 | ||
345 | for (node = cgraph_nodes; node; node = node->next) | |
346 | for (cs = node->callees; cs; cs = cs->next_callee) | |
dcd416e3 | 347 | cs->aux = xcalloc (1, sizeof (struct ipa_edge_args)); |
518dc859 RL |
348 | } |
349 | ||
350 | /* Free ipa_edge structure. */ | |
351 | void | |
dcd416e3 | 352 | ipa_free_all_edge_args (void) |
518dc859 RL |
353 | { |
354 | struct cgraph_node *node; | |
355 | struct cgraph_edge *cs; | |
356 | ||
357 | for (node = cgraph_nodes; node; node = node->next) | |
358 | for (cs = node->callees; cs; cs = cs->next_callee) | |
dcd416e3 MJ |
359 | if (cs->aux) |
360 | { | |
361 | if (IPA_EDGE_REF (cs)->jump_functions) | |
362 | free (IPA_EDGE_REF (cs)->jump_functions); | |
363 | free (cs->aux); | |
364 | cs->aux = NULL; | |
365 | } | |
518dc859 RL |
366 | } |
367 | ||
dcd416e3 | 368 | /* Free ipa data structures of ipa_node_params and ipa_edge_args. */ |
518dc859 | 369 | void |
dcd416e3 | 370 | ipa_free_all_node_params (void) |
518dc859 RL |
371 | { |
372 | struct cgraph_node *node; | |
518dc859 RL |
373 | |
374 | for (node = cgraph_nodes; node; node = node->next) | |
375 | { | |
376 | if (node->aux == NULL) | |
377 | continue; | |
dcd416e3 MJ |
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); | |
384 | free (node->aux); | |
385 | node->aux = NULL; | |
518dc859 RL |
386 | } |
387 | } | |
388 | ||
dcd416e3 | 389 | /* Print ipa_tree_map data structures of all functions in the |
518dc859 RL |
390 | callgraph to F. */ |
391 | void | |
dcd416e3 | 392 | ipa_print_all_tree_maps (FILE * f) |
518dc859 RL |
393 | { |
394 | int i, count; | |
395 | tree temp; | |
396 | struct cgraph_node *node; | |
397 | ||
398 | fprintf (f, "\nPARAM TREE MAP PRINT\n"); | |
399 | for (node = cgraph_nodes; node; node = node->next) | |
400 | { | |
dcd416e3 MJ |
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); | |
518dc859 RL |
404 | for (i = 0; i < count; i++) |
405 | { | |
dcd416e3 | 406 | temp = ipa_get_ith_param (info, i); |
518dc859 RL |
407 | if (TREE_CODE (temp) == PARM_DECL) |
408 | fprintf (f, " param [%d] : %s\n", i, | |
409 | (*lang_hooks.decl_printable_name) (temp, 2)); | |
410 | } | |
411 | ||
412 | } | |
413 | } | |
414 | ||
dcd416e3 | 415 | /* Print modified_flags data structures of all functions in the |
518dc859 RL |
416 | callgraph to F. */ |
417 | void | |
dcd416e3 | 418 | ipa_print_all_params_modified (FILE * f) |
518dc859 RL |
419 | { |
420 | int i, count; | |
421 | bool temp; | |
422 | struct cgraph_node *node; | |
423 | ||
424 | fprintf (f, "\nMODIFY PRINT\n"); | |
425 | for (node = cgraph_nodes; node; node = node->next) | |
426 | { | |
dcd416e3 MJ |
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); | |
518dc859 RL |
430 | for (i = 0; i < count; i++) |
431 | { | |
dcd416e3 | 432 | temp = info->modified_flags[i]; |
518dc859 RL |
433 | if (temp) |
434 | fprintf (f, " param [%d] true \n", i); | |
435 | else | |
436 | fprintf (f, " param [%d] false \n", i); | |
437 | } | |
438 | } | |
439 | } | |
dcd416e3 | 440 |