00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tree.h"
00025 #include "langhooks.h"
00026 #include "ggc.h"
00027 #include "target.h"
00028 #include "cgraph.h"
00029 #include "ipa-prop.h"
00030 #include "tree-flow.h"
00031 #include "tree-pass.h"
00032 #include "flags.h"
00033 #include "timevar.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 static inline ipa_methodlist_p
00052 ipa_create_methodlist_node (void)
00053 {
00054 return (ipa_methodlist_p) xcalloc (1, sizeof (struct ipa_methodlist));
00055 }
00056
00057
00058 bool
00059 ipa_methodlist_not_empty (ipa_methodlist_p wl)
00060 {
00061 return (wl != NULL);
00062 }
00063
00064
00065 static inline struct cgraph_node *
00066 ipa_methodlist_method (ipa_methodlist_p wl)
00067 {
00068 return wl->method_p;
00069 }
00070
00071
00072 static inline void
00073 ipa_methodlist_method_set (ipa_methodlist_p wl, struct cgraph_node *mt)
00074 {
00075 wl->method_p = mt;
00076 }
00077
00078
00079
00080 static inline ipa_methodlist_p
00081 ipa_methodlist_next_method (ipa_methodlist_p wl)
00082 {
00083 return wl->next_method;
00084 }
00085
00086
00087 static inline void
00088 ipa_methodlist_next_method_set (ipa_methodlist_p wl1, ipa_methodlist_p wl2)
00089 {
00090 wl1->next_method = wl2;
00091 }
00092
00093
00094 ipa_methodlist_p
00095 ipa_methodlist_init (void)
00096 {
00097 struct cgraph_node *node;
00098 ipa_methodlist_p wl;
00099
00100 wl = NULL;
00101 for (node = cgraph_nodes; node; node = node->next)
00102 ipa_add_method (&wl, node);
00103
00104 return wl;
00105 }
00106
00107
00108
00109 void
00110 ipa_add_method (ipa_methodlist_p * wl, struct cgraph_node *mt)
00111 {
00112 ipa_methodlist_p temp;
00113
00114 temp = ipa_create_methodlist_node ();
00115 ipa_methodlist_method_set (temp, mt);
00116 ipa_methodlist_next_method_set (temp, *wl);
00117 *wl = temp;
00118 }
00119
00120
00121
00122 struct cgraph_node *
00123 ipa_remove_method (ipa_methodlist_p * wl)
00124 {
00125 ipa_methodlist_p first;
00126 struct cgraph_node *return_method;
00127
00128 first = *wl;
00129 *wl = ipa_methodlist_next_method (*wl);
00130 return_method = ipa_methodlist_method (first);
00131 free (first);
00132 return return_method;
00133 }
00134
00135
00136
00137
00138 int
00139 ipa_method_formal_count (struct cgraph_node *mt)
00140 {
00141 return IPA_NODE_REF (mt)->ipa_arg_num;
00142 }
00143
00144
00145 void
00146 ipa_method_formal_count_set (struct cgraph_node *mt, int i)
00147 {
00148 IPA_NODE_REF (mt)->ipa_arg_num = i;
00149 }
00150
00151
00152 static inline bool
00153 ipa_method_is_modified (struct cgraph_node *mt, int i)
00154 {
00155 return IPA_NODE_REF (mt)->ipa_mod[i];
00156 }
00157
00158
00159 tree
00160 ipa_method_get_tree (struct cgraph_node *mt, int i)
00161 {
00162 return IPA_NODE_REF (mt)->ipa_param_tree[i];
00163 }
00164
00165
00166 static inline void
00167 ipa_method_tree_map_create (struct cgraph_node *mt)
00168 {
00169 IPA_NODE_REF (mt)->ipa_param_tree =
00170 XCNEWVEC (tree, ipa_method_formal_count (mt));
00171 }
00172
00173
00174 static inline void
00175 ipa_method_modify_create (struct cgraph_node *mt)
00176 {
00177 ((struct ipa_node *) mt->aux)->ipa_mod =
00178 XCNEWVEC (bool, ipa_method_formal_count (mt));
00179 }
00180
00181
00182 static inline void
00183 ipa_method_modify_set (struct cgraph_node *mt, int i, bool val)
00184 {
00185 IPA_NODE_REF (mt)->ipa_mod[i] = val;
00186 }
00187
00188
00189 static int
00190 ipa_method_tree_map (struct cgraph_node *mt, tree ptree)
00191 {
00192 int i, count;
00193
00194 count = ipa_method_formal_count (mt);
00195 for (i = 0; i < count; i++)
00196 if (IPA_NODE_REF (mt)->ipa_param_tree[i] == ptree)
00197 return i;
00198
00199 return -1;
00200 }
00201
00202
00203 void
00204 ipa_method_compute_tree_map (struct cgraph_node *mt)
00205 {
00206 tree fndecl;
00207 tree fnargs;
00208 tree parm;
00209 int param_num;
00210
00211 ipa_method_tree_map_create (mt);
00212 fndecl = mt->decl;
00213 fnargs = DECL_ARGUMENTS (fndecl);
00214 param_num = 0;
00215 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
00216 {
00217 IPA_NODE_REF (mt)->ipa_param_tree[param_num] = parm;
00218 param_num++;
00219 }
00220 }
00221
00222
00223
00224 void
00225 ipa_method_formal_compute_count (struct cgraph_node *mt)
00226 {
00227 tree fndecl;
00228 tree fnargs;
00229 tree parm;
00230 int param_num;
00231
00232 fndecl = mt->decl;
00233 fnargs = DECL_ARGUMENTS (fndecl);
00234 param_num = 0;
00235 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
00236 param_num++;
00237 ipa_method_formal_count_set (mt, param_num);
00238 }
00239
00240
00241
00242
00243 static void
00244 ipa_method_modify_stmt (struct cgraph_node *mt, tree stmt)
00245 {
00246 int i, j;
00247
00248 switch (TREE_CODE (stmt))
00249 {
00250 case MODIFY_EXPR:
00251 if (TREE_CODE (TREE_OPERAND (stmt, 0)) == PARM_DECL)
00252 {
00253 i = ipa_method_tree_map (mt, TREE_OPERAND (stmt, 0));
00254 if (i >= 0)
00255 ipa_method_modify_set (mt, i, true);
00256 }
00257 break;
00258 case ASM_EXPR:
00259
00260 for (j = 0; j < ipa_method_formal_count (mt); j++)
00261 ipa_method_modify_set (mt, j, true);
00262 break;
00263 default:
00264 break;
00265 }
00266 }
00267
00268
00269 static void
00270 ipa_method_modify_init (struct cgraph_node *mt)
00271 {
00272 int i, count;
00273
00274 ipa_method_modify_create (mt);
00275 count = ipa_method_formal_count (mt);
00276 for (i = 0; i < count; i++)
00277 ipa_method_modify_set (mt, i, false);
00278 }
00279
00280
00281
00282
00283
00284 void
00285 ipa_method_compute_modify (struct cgraph_node *mt)
00286 {
00287 tree decl;
00288 tree body;
00289 int j, count;
00290 basic_block bb;
00291 struct function *func;
00292 block_stmt_iterator bsi;
00293 tree stmt, parm_tree;
00294
00295 ipa_method_modify_init (mt);
00296 decl = mt->decl;
00297 count = ipa_method_formal_count (mt);
00298
00299
00300 if (DECL_UNINLINABLE (decl))
00301 {
00302 for (j = 0; j < count; j++)
00303 ipa_method_modify_set (mt, j, true);
00304 return;
00305 }
00306
00307 for (j = 0; j < count; j++)
00308 {
00309 parm_tree = ipa_method_get_tree (mt, j);
00310 if (TREE_ADDRESSABLE (parm_tree))
00311 ipa_method_modify_set (mt, j, true);
00312 }
00313 body = DECL_SAVED_TREE (decl);
00314 if (body != NULL)
00315 {
00316 func = DECL_STRUCT_FUNCTION (decl);
00317 FOR_EACH_BB_FN (bb, func)
00318 {
00319 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00320 {
00321 stmt = bsi_stmt (bsi);
00322 ipa_method_modify_stmt (mt, stmt);
00323 }
00324 }
00325 }
00326 }
00327
00328
00329
00330
00331
00332 int
00333 ipa_callsite_param_count (struct cgraph_edge *cs)
00334 {
00335 return IPA_EDGE_REF (cs)->ipa_param_num;
00336 }
00337
00338
00339 void
00340 ipa_callsite_param_count_set (struct cgraph_edge *cs, int i)
00341 {
00342 IPA_EDGE_REF (cs)->ipa_param_num = i;
00343 }
00344
00345
00346
00347 struct ipa_jump_func *
00348 ipa_callsite_param (struct cgraph_edge *cs, int i)
00349 {
00350 return &(IPA_EDGE_REF (cs)->ipa_param_map[i]);
00351 }
00352
00353
00354 struct cgraph_node *
00355 ipa_callsite_callee (struct cgraph_edge *cs)
00356 {
00357 return cs->callee;
00358 }
00359
00360
00361
00362 static inline void
00363 ipa_callsite_param_set_type (struct cgraph_edge *cs, int i,
00364 enum jump_func_type type1)
00365 {
00366 IPA_EDGE_REF (cs)->ipa_param_map[i].type = type1;
00367 }
00368
00369
00370
00371 static inline void
00372 ipa_callsite_param_set_info_type_formal (struct cgraph_edge *cs, int i,
00373 unsigned int formal)
00374 {
00375 ipa_callsite_param (cs, i)->info_type.formal_id = formal;
00376 }
00377
00378
00379
00380 static inline void
00381 ipa_callsite_param_set_info_type (struct cgraph_edge *cs, int i, tree info_type1)
00382 {
00383 ipa_callsite_param (cs, i)->info_type.value = info_type1;
00384 }
00385
00386
00387 static inline void
00388 ipa_callsite_param_map_create (struct cgraph_edge *cs)
00389 {
00390 IPA_EDGE_REF (cs)->ipa_param_map =
00391 XCNEWVEC (struct ipa_jump_func, ipa_callsite_param_count (cs));
00392 }
00393
00394
00395 static inline tree
00396 ipa_callsite_tree (struct cgraph_edge *cs)
00397 {
00398 return cs->call_stmt;
00399 }
00400
00401
00402 static inline struct cgraph_node *
00403 ipa_callsite_caller (struct cgraph_edge *cs)
00404 {
00405 return cs->caller;
00406 }
00407
00408
00409
00410 void
00411 ipa_callsite_compute_count (struct cgraph_edge *cs)
00412 {
00413 tree call_tree;
00414 tree arg;
00415 int arg_num;
00416
00417 call_tree = get_call_expr_in (ipa_callsite_tree (cs));
00418 gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
00419 arg = TREE_OPERAND (call_tree, 1);
00420 arg_num = 0;
00421 for (; arg != NULL_TREE; arg = TREE_CHAIN (arg))
00422 arg_num++;
00423 ipa_callsite_param_count_set (cs, arg_num);
00424 }
00425
00426
00427
00428
00429
00430 void
00431 ipa_callsite_compute_param (struct cgraph_edge *cs)
00432 {
00433 tree call_tree;
00434 tree arg, cst_decl;
00435 int arg_num;
00436 int i;
00437 struct cgraph_node *mt;
00438
00439 if (ipa_callsite_param_count (cs) == 0)
00440 return;
00441 ipa_callsite_param_map_create (cs);
00442 call_tree = get_call_expr_in (ipa_callsite_tree (cs));
00443 gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
00444 arg = TREE_OPERAND (call_tree, 1);
00445 arg_num = 0;
00446
00447 for (; arg != NULL_TREE; arg = TREE_CHAIN (arg))
00448 {
00449
00450
00451
00452 if (TREE_CODE (TREE_VALUE (arg)) == PARM_DECL)
00453 {
00454 mt = ipa_callsite_caller (cs);
00455 i = ipa_method_tree_map (mt, TREE_VALUE (arg));
00456 if (i < 0 || ipa_method_is_modified (mt, i))
00457 ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
00458 else
00459 {
00460 ipa_callsite_param_set_type (cs, arg_num, FORMAL_IPATYPE);
00461 ipa_callsite_param_set_info_type_formal (cs, arg_num, i);
00462 }
00463 }
00464
00465
00466
00467 else if (TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
00468 || TREE_CODE (TREE_VALUE (arg)) == REAL_CST)
00469 {
00470 ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE);
00471 ipa_callsite_param_set_info_type (cs, arg_num,
00472 TREE_VALUE (arg));
00473 }
00474
00475
00476
00477
00478 else if (TREE_CODE (TREE_VALUE (arg)) == ADDR_EXPR
00479 && TREE_CODE (TREE_OPERAND (TREE_VALUE (arg), 0)) ==
00480 CONST_DECL)
00481 {
00482 cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0);
00483 if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST
00484 || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST)
00485 {
00486 ipa_callsite_param_set_type (cs, arg_num,
00487 CONST_IPATYPE_REF);
00488 ipa_callsite_param_set_info_type (cs, arg_num,
00489 DECL_INITIAL (cst_decl));
00490 }
00491 }
00492 else
00493 ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
00494 arg_num++;
00495 }
00496 }
00497
00498
00499 enum jump_func_type
00500 get_type (struct ipa_jump_func *jf)
00501 {
00502 return jf->type;
00503 }
00504
00505
00506 union parameter_info *
00507 ipa_jf_get_info_type (struct ipa_jump_func *jf)
00508 {
00509 return &(jf->info_type);
00510 }
00511
00512
00513
00514 void
00515 ipa_node_create (struct cgraph_node *node)
00516 {
00517 node->aux = xcalloc (1, sizeof (struct ipa_node));
00518 }
00519
00520
00521
00522 void
00523 ipa_nodes_create (void)
00524 {
00525 struct cgraph_node *node;
00526
00527 for (node = cgraph_nodes; node; node = node->next)
00528 ipa_node_create (node);
00529 }
00530
00531
00532 void
00533 ipa_edges_create (void)
00534 {
00535 struct cgraph_node *node;
00536 struct cgraph_edge *cs;
00537
00538 for (node = cgraph_nodes; node; node = node->next)
00539 for (cs = node->callees; cs; cs = cs->next_callee)
00540 cs->aux = xcalloc (1, sizeof (struct ipa_edge));
00541 }
00542
00543
00544 void
00545 ipa_nodes_free (void)
00546 {
00547 struct cgraph_node *node;
00548
00549 for (node = cgraph_nodes; node; node = node->next)
00550 {
00551 free (node->aux);
00552 node->aux = NULL;
00553 }
00554 }
00555
00556
00557 void
00558 ipa_edges_free (void)
00559 {
00560 struct cgraph_node *node;
00561 struct cgraph_edge *cs;
00562
00563 for (node = cgraph_nodes; node; node = node->next)
00564 for (cs = node->callees; cs; cs = cs->next_callee)
00565 {
00566 free (cs->aux);
00567 cs->aux = NULL;
00568 }
00569 }
00570
00571
00572 void
00573 ipa_free (void)
00574 {
00575 struct cgraph_node *node;
00576 struct cgraph_edge *cs;
00577
00578 for (node = cgraph_nodes; node; node = node->next)
00579 {
00580 if (node->aux == NULL)
00581 continue;
00582 if (IPA_NODE_REF (node)->ipcp_cval)
00583 free (IPA_NODE_REF (node)->ipcp_cval);
00584 if (IPA_NODE_REF (node)->ipa_param_tree)
00585 free (IPA_NODE_REF (node)->ipa_param_tree);
00586 if (IPA_NODE_REF (node)->ipa_mod)
00587 free (IPA_NODE_REF (node)->ipa_mod);
00588 for (cs = node->callees; cs; cs = cs->next_callee)
00589 {
00590 if (cs->aux)
00591 if (IPA_EDGE_REF (cs)->ipa_param_map)
00592 free (IPA_EDGE_REF (cs)->ipa_param_map);
00593 }
00594 }
00595 }
00596
00597
00598
00599 void
00600 ipa_method_tree_print (FILE * f)
00601 {
00602 int i, count;
00603 tree temp;
00604 struct cgraph_node *node;
00605
00606 fprintf (f, "\nPARAM TREE MAP PRINT\n");
00607 for (node = cgraph_nodes; node; node = node->next)
00608 {
00609 fprintf (f, "method %s Trees :: \n", cgraph_node_name (node));
00610 count = ipa_method_formal_count (node);
00611 for (i = 0; i < count; i++)
00612 {
00613 temp = ipa_method_get_tree (node, i);
00614 if (TREE_CODE (temp) == PARM_DECL)
00615 fprintf (f, " param [%d] : %s\n", i,
00616 (*lang_hooks.decl_printable_name) (temp, 2));
00617 }
00618
00619 }
00620 }
00621
00622
00623
00624 void
00625 ipa_method_modify_print (FILE * f)
00626 {
00627 int i, count;
00628 bool temp;
00629 struct cgraph_node *node;
00630
00631 fprintf (f, "\nMODIFY PRINT\n");
00632 for (node = cgraph_nodes; node; node = node->next)
00633 {
00634 fprintf (f, "method %s :: \n", cgraph_node_name (node));
00635 count = ipa_method_formal_count (node);
00636 for (i = 0; i < count; i++)
00637 {
00638 temp = ipa_method_is_modified (node, i);
00639 if (temp)
00640 fprintf (f, " param [%d] true \n", i);
00641 else
00642 fprintf (f, " param [%d] false \n", i);
00643 }
00644 }
00645 }