00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 #include "config.h"
00135 #include "system.h"
00136 #include "coretypes.h"
00137 #include "tree.h"
00138 #include "target.h"
00139 #include "cgraph.h"
00140 #include "ipa-prop.h"
00141 #include "tree-flow.h"
00142 #include "tree-pass.h"
00143 #include "flags.h"
00144 #include "timevar.h"
00145 #include "diagnostic.h"
00146
00147
00148 static inline struct cgraph_node *
00149 ipcp_method_orig_node (struct cgraph_node *mt)
00150 {
00151 return IPA_NODE_REF (mt)->ipcp_orig_node;
00152 }
00153
00154
00155 static inline bool
00156 ipcp_method_is_cloned (struct cgraph_node *node)
00157 {
00158 return (ipcp_method_orig_node (node) != NULL);
00159 }
00160
00161
00162 static inline void
00163 ipcp_method_set_orig_node (struct cgraph_node *node,
00164 struct cgraph_node *orig_node)
00165 {
00166 IPA_NODE_REF (node)->ipcp_orig_node = orig_node;
00167 }
00168
00169
00170
00171 static void
00172 ipcp_cloned_create (struct cgraph_node *orig_node,
00173 struct cgraph_node *new_node)
00174 {
00175 ipa_node_create (new_node);
00176 ipcp_method_set_orig_node (new_node, orig_node);
00177 ipa_method_formal_compute_count (new_node);
00178 ipa_method_compute_tree_map (new_node);
00179 }
00180
00181
00182 static inline enum cvalue_type
00183 ipcp_cval_get_cvalue_type (struct ipcp_formal *cval)
00184 {
00185 return cval->cval_type;
00186 }
00187
00188
00189 static inline gcov_type
00190 ipcp_method_get_scale (struct cgraph_node *mt)
00191 {
00192 return IPA_NODE_REF (mt)->count_scale;
00193 }
00194
00195
00196 static inline void
00197 ipcp_method_set_scale (struct cgraph_node *node, gcov_type count)
00198 {
00199 IPA_NODE_REF (node)->count_scale = count;
00200 }
00201
00202
00203 static inline void
00204 ipcp_cval_set_cvalue_type (struct ipcp_formal *cval, enum cvalue_type type)
00205 {
00206 cval->cval_type = type;
00207 }
00208
00209
00210 static inline union parameter_info *
00211 ipcp_cval_get_cvalue (struct ipcp_formal *cval)
00212 {
00213 return &(cval->cvalue);
00214 }
00215
00216
00217 static inline void
00218 ipcp_cval_set_cvalue (struct ipcp_formal *cval, union parameter_info *value,
00219 enum cvalue_type type)
00220 {
00221 if (type == CONST_VALUE || type == CONST_VALUE_REF)
00222 cval->cvalue.value = value->value;
00223 }
00224
00225
00226 static bool
00227 ipcp_type_is_const (enum cvalue_type type)
00228 {
00229 if (type == CONST_VALUE || type == CONST_VALUE_REF)
00230 return true;
00231 else
00232 return false;
00233 }
00234
00235
00236 static inline bool
00237 ipcp_cval_equal_cvalues (union parameter_info *const_val1,
00238 union parameter_info *const_val2,
00239 enum cvalue_type type1, enum cvalue_type type2)
00240 {
00241 gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2));
00242 if (type1 != type2)
00243 return false;
00244
00245 if (operand_equal_p (const_val1->value, const_val2->value, 0))
00246 return true;
00247
00248 return false;
00249 }
00250
00251
00252
00253
00254
00255
00256 static void
00257 ipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1,
00258 struct ipcp_formal *cval2)
00259 {
00260 if (ipcp_cval_get_cvalue_type (cval1) == BOTTOM
00261 || ipcp_cval_get_cvalue_type (cval2) == BOTTOM)
00262 {
00263 ipcp_cval_set_cvalue_type (cval, BOTTOM);
00264 return;
00265 }
00266 if (ipcp_cval_get_cvalue_type (cval1) == TOP)
00267 {
00268 ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval2));
00269 ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2),
00270 ipcp_cval_get_cvalue_type (cval2));
00271 return;
00272 }
00273 if (ipcp_cval_get_cvalue_type (cval2) == TOP)
00274 {
00275 ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
00276 ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
00277 ipcp_cval_get_cvalue_type (cval1));
00278 return;
00279 }
00280 if (!ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
00281 ipcp_cval_get_cvalue (cval2),
00282 ipcp_cval_get_cvalue_type (cval1),
00283 ipcp_cval_get_cvalue_type (cval2)))
00284 {
00285 ipcp_cval_set_cvalue_type (cval, BOTTOM);
00286 return;
00287 }
00288 ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
00289 ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
00290 ipcp_cval_get_cvalue_type (cval1));
00291 }
00292
00293
00294 static inline struct ipcp_formal *
00295 ipcp_method_cval (struct cgraph_node *mt, int info_type)
00296 {
00297 return &(IPA_NODE_REF (mt)->ipcp_cval[info_type]);
00298 }
00299
00300
00301
00302
00303 static void
00304 ipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt,
00305 enum jump_func_type type, union parameter_info *info_type)
00306 {
00307 if (type == UNKNOWN_IPATYPE)
00308 ipcp_cval_set_cvalue_type (cval, BOTTOM);
00309 else if (type == CONST_IPATYPE)
00310 {
00311 ipcp_cval_set_cvalue_type (cval, CONST_VALUE);
00312 ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE);
00313 }
00314 else if (type == CONST_IPATYPE_REF)
00315 {
00316 ipcp_cval_set_cvalue_type (cval, CONST_VALUE_REF);
00317 ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE_REF);
00318 }
00319 else if (type == FORMAL_IPATYPE)
00320 {
00321 enum cvalue_type type =
00322 ipcp_cval_get_cvalue_type (ipcp_method_cval
00323 (mt, info_type->formal_id));
00324 ipcp_cval_set_cvalue_type (cval, type);
00325 ipcp_cval_set_cvalue (cval,
00326 ipcp_cval_get_cvalue (ipcp_method_cval
00327 (mt, info_type->formal_id)),
00328 type);
00329 }
00330 }
00331
00332
00333 static bool
00334 ipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2)
00335 {
00336 if (ipcp_cval_get_cvalue_type (cval1) == ipcp_cval_get_cvalue_type (cval2))
00337 {
00338 if (ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE &&
00339 ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE_REF)
00340 return false;
00341 if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
00342 ipcp_cval_get_cvalue (cval2),
00343 ipcp_cval_get_cvalue_type (cval1),
00344 ipcp_cval_get_cvalue_type (cval2)))
00345 return false;
00346 }
00347 return true;
00348 }
00349
00350
00351 static inline void
00352 ipcp_formal_create (struct cgraph_node *mt)
00353 {
00354 IPA_NODE_REF (mt)->ipcp_cval =
00355 XCNEWVEC (struct ipcp_formal, ipa_method_formal_count (mt));
00356 }
00357
00358
00359 static inline void
00360 ipcp_method_cval_set (struct cgraph_node *mt, int i, struct ipcp_formal *cval)
00361 {
00362 IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval->cval_type;
00363 ipcp_cval_set_cvalue (ipcp_method_cval (mt, i),
00364 ipcp_cval_get_cvalue (cval), cval->cval_type);
00365 }
00366
00367
00368 static inline void
00369 ipcp_method_cval_set_cvalue_type (struct cgraph_node *mt, int i,
00370 enum cvalue_type cval_type1)
00371 {
00372 IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval_type1;
00373 }
00374
00375
00376 static void
00377 ipcp_method_cval_print (FILE * f)
00378 {
00379 struct cgraph_node *node;
00380 int i, count;
00381 tree cvalue;
00382
00383 fprintf (f, "\nCVAL PRINT\n");
00384 for (node = cgraph_nodes; node; node = node->next)
00385 {
00386 fprintf (f, "Printing cvals %s:\n", cgraph_node_name (node));
00387 count = ipa_method_formal_count (node);
00388 for (i = 0; i < count; i++)
00389 {
00390 if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i))
00391 == CONST_VALUE
00392 || ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) ==
00393 CONST_VALUE_REF)
00394 {
00395 fprintf (f, " param [%d]: ", i);
00396 fprintf (f, "type is CONST ");
00397 cvalue =
00398 ipcp_cval_get_cvalue (ipcp_method_cval (node, i))->
00399 value;
00400 print_generic_expr (f, cvalue, 0);
00401 fprintf (f, "\n");
00402 }
00403 else if (ipcp_method_cval (node, i)->cval_type == TOP)
00404 fprintf (f, "param [%d]: type is TOP \n", i);
00405 else
00406 fprintf (f, "param [%d]: type is BOTTOM \n", i);
00407 }
00408 }
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 static void
00418 ipcp_method_cval_init (struct cgraph_node *mt)
00419 {
00420 int i;
00421 tree parm_tree;
00422
00423 ipcp_formal_create (mt);
00424 for (i = 0; i < ipa_method_formal_count (mt); i++)
00425 {
00426 parm_tree = ipa_method_get_tree (mt, i);
00427 if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
00428 || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
00429 || POINTER_TYPE_P (TREE_TYPE (parm_tree)))
00430 ipcp_method_cval_set_cvalue_type (mt, i, TOP);
00431 else
00432 ipcp_method_cval_set_cvalue_type (mt, i, BOTTOM);
00433 }
00434 }
00435
00436
00437
00438
00439
00440
00441 static void
00442 constant_val_insert (tree fn, tree parm1, tree val)
00443 {
00444 struct function *func;
00445 tree init_stmt;
00446 edge e_step;
00447 edge_iterator ei;
00448
00449 init_stmt = build2 (MODIFY_EXPR, void_type_node, parm1, val);
00450 func = DECL_STRUCT_FUNCTION (fn);
00451 cfun = func;
00452 current_function_decl = fn;
00453 if (ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
00454 FOR_EACH_EDGE (e_step, ei, ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
00455 bsi_insert_on_edge_immediate (e_step, init_stmt);
00456 }
00457
00458
00459
00460 static tree
00461 build_const_val (union parameter_info *cvalue, enum cvalue_type type,
00462 tree tree_type)
00463 {
00464 tree const_val = NULL;
00465
00466 gcc_assert (ipcp_type_is_const (type));
00467 const_val = fold_convert (tree_type, cvalue->value);
00468 return const_val;
00469 }
00470
00471
00472
00473 static void
00474 ipcp_propagate_const (struct cgraph_node *mt, int param,
00475 union parameter_info *cvalue ,enum cvalue_type type)
00476 {
00477 tree fndecl;
00478 tree const_val;
00479 tree parm_tree;
00480
00481 if (dump_file)
00482 fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt));
00483 fndecl = mt->decl;
00484 parm_tree = ipa_method_get_tree (mt, param);
00485 const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
00486 constant_val_insert (fndecl, parm_tree, const_val);
00487 }
00488
00489
00490
00491
00492
00493 static void
00494 ipcp_method_compute_scale (struct cgraph_node *node)
00495 {
00496 gcov_type sum;
00497 struct cgraph_edge *cs;
00498
00499 sum = 0;
00500
00501 for (cs = node->callers; cs != NULL; cs = cs->next_caller)
00502 sum += cs->count;
00503 if (node->count == 0)
00504 ipcp_method_set_scale (node, 0);
00505 else
00506 ipcp_method_set_scale (node, sum * REG_BR_PROB_BASE / node->count);
00507 }
00508
00509
00510
00511
00512
00513 static void
00514 ipcp_init_stage (void)
00515 {
00516 struct cgraph_node *node;
00517 struct cgraph_edge *cs;
00518
00519 for (node = cgraph_nodes; node; node = node->next)
00520 {
00521 ipa_method_formal_compute_count (node);
00522 ipa_method_compute_tree_map (node);
00523 ipcp_method_cval_init (node);
00524 ipa_method_compute_modify (node);
00525 ipcp_method_compute_scale (node);
00526 }
00527 for (node = cgraph_nodes; node; node = node->next)
00528 {
00529
00530 for (cs = node->callees; cs; cs = cs->next_callee)
00531 {
00532 ipa_callsite_compute_count (cs);
00533 if (ipa_callsite_param_count (cs)
00534 != ipa_method_formal_count (cs->callee))
00535 {
00536
00537
00538 ipa_callsite_param_count_set (cs, 0);
00539 ipa_method_formal_count_set (cs->callee, 0);
00540 }
00541 else
00542 ipa_callsite_compute_param (cs);
00543 }
00544 }
00545 }
00546
00547
00548
00549 static bool
00550 ipcp_after_propagate (void)
00551 {
00552 int i, count;
00553 struct cgraph_node *node;
00554 bool prop_again;
00555
00556 prop_again = false;
00557 for (node = cgraph_nodes; node; node = node->next)
00558 {
00559 count = ipa_method_formal_count (node);
00560 for (i = 0; i < count; i++)
00561 if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP)
00562 {
00563 prop_again = true;
00564 ipcp_method_cval_set_cvalue_type (node, i, BOTTOM);
00565 }
00566 }
00567 return prop_again;
00568 }
00569
00570
00571
00572 static void
00573 ipcp_propagate_stage (void)
00574 {
00575 int i;
00576 struct ipcp_formal cval1 = { 0, {0} }, cval = { 0,{0} };
00577 struct ipcp_formal *cval2;
00578 struct cgraph_node *mt, *callee;
00579 struct cgraph_edge *cs;
00580 struct ipa_jump_func *jump_func;
00581 enum jump_func_type type;
00582 union parameter_info *info_type;
00583 ipa_methodlist_p wl;
00584 int count;
00585
00586
00587 wl = ipa_methodlist_init ();
00588 while (ipa_methodlist_not_empty (wl))
00589 {
00590 mt = ipa_remove_method (&wl);
00591 for (cs = mt->callees; cs; cs = cs->next_callee)
00592 {
00593 callee = ipa_callsite_callee (cs);
00594 count = ipa_callsite_param_count (cs);
00595 for (i = 0; i < count; i++)
00596 {
00597 jump_func = ipa_callsite_param (cs, i);
00598 type = get_type (jump_func);
00599 info_type = ipa_jf_get_info_type (jump_func);
00600 ipcp_cval_compute (&cval1, mt, type, info_type);
00601 cval2 = ipcp_method_cval (callee, i);
00602 ipcp_cval_meet (&cval, &cval1, cval2);
00603 if (ipcp_cval_changed (&cval, cval2))
00604 {
00605 ipcp_method_cval_set (callee, i, &cval);
00606 ipa_add_method (&wl, callee);
00607 }
00608 }
00609 }
00610 }
00611 }
00612
00613
00614
00615 static void
00616 ipcp_iterate_stage (void)
00617 {
00618 ipcp_propagate_stage ();
00619 if (ipcp_after_propagate ())
00620
00621
00622 ipcp_propagate_stage ();
00623 }
00624
00625
00626 static bool
00627 ipcp_method_dont_insert_const (struct cgraph_node *mt)
00628 {
00629
00630 if (DECL_UNINLINABLE (mt->decl))
00631 return true;
00632 return false;
00633 }
00634
00635
00636 static void
00637 ipcp_callsite_param_print (FILE * f)
00638 {
00639 struct cgraph_node *node;
00640 int i, count;
00641 struct cgraph_edge *cs;
00642 struct ipa_jump_func *jump_func;
00643 enum jump_func_type type;
00644 tree info_type;
00645
00646 fprintf (f, "\nCALLSITE PARAM PRINT\n");
00647 for (node = cgraph_nodes; node; node = node->next)
00648 {
00649 for (cs = node->callees; cs; cs = cs->next_callee)
00650 {
00651 fprintf (f, "callsite %s ", cgraph_node_name (node));
00652 fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
00653 count = ipa_callsite_param_count (cs);
00654 for (i = 0; i < count; i++)
00655 {
00656 jump_func = ipa_callsite_param (cs, i);
00657 type = get_type (jump_func);
00658
00659 fprintf (f, " param %d: ", i);
00660 if (type == UNKNOWN_IPATYPE)
00661 fprintf (f, "UNKNOWN\n");
00662 else if (type == CONST_IPATYPE || type == CONST_IPATYPE_REF)
00663 {
00664 info_type =
00665 ipa_jf_get_info_type (jump_func)->value;
00666 fprintf (f, "CONST : ");
00667 print_generic_expr (f, info_type, 0);
00668 fprintf (f, "\n");
00669 }
00670 else if (type == FORMAL_IPATYPE)
00671 {
00672 fprintf (f, "FORMAL : ");
00673 fprintf (f, "%d\n",
00674 ipa_jf_get_info_type (jump_func)->formal_id);
00675 }
00676 }
00677 }
00678 }
00679 }
00680
00681
00682 static void
00683 ipcp_method_scale_print (FILE * f)
00684 {
00685 struct cgraph_node *node;
00686
00687 for (node = cgraph_nodes; node; node = node->next)
00688 {
00689 fprintf (f, "printing scale for %s: ", cgraph_node_name (node));
00690 fprintf (f, "value is " HOST_WIDE_INT_PRINT_DEC
00691 " \n", (HOST_WIDE_INT) ipcp_method_get_scale (node));
00692 }
00693 }
00694
00695
00696 static void
00697 ipcp_profile_mt_count_print (FILE * f)
00698 {
00699 struct cgraph_node *node;
00700
00701 for (node = cgraph_nodes; node; node = node->next)
00702 {
00703 fprintf (f, "method %s: ", cgraph_node_name (node));
00704 fprintf (f, "count is " HOST_WIDE_INT_PRINT_DEC
00705 " \n", (HOST_WIDE_INT) node->count);
00706 }
00707 }
00708
00709
00710 static void
00711 ipcp_profile_cs_count_print (FILE * f)
00712 {
00713 struct cgraph_node *node;
00714 struct cgraph_edge *cs;
00715
00716 for (node = cgraph_nodes; node; node = node->next)
00717 {
00718 for (cs = node->callees; cs; cs = cs->next_callee)
00719 {
00720 fprintf (f, "%s -> %s ", cgraph_node_name (cs->caller),
00721 cgraph_node_name (cs->callee));
00722 fprintf (f, "count is " HOST_WIDE_INT_PRINT_DEC " \n",
00723 (HOST_WIDE_INT) cs->count);
00724 }
00725 }
00726 }
00727
00728
00729 static void
00730 ipcp_profile_edge_print (FILE * f)
00731 {
00732 struct cgraph_node *node;
00733 basic_block bb;
00734 edge_iterator ei;
00735 edge e;
00736
00737 for (node = cgraph_nodes; node; node = node->next)
00738 {
00739 fprintf (f, "method %s: \n", cgraph_node_name (node));
00740 if (DECL_SAVED_TREE (node->decl))
00741 {
00742 bb =
00743 ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
00744 fprintf (f, "ENTRY: ");
00745 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
00746 " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
00747
00748 if (bb->succs)
00749 FOR_EACH_EDGE (e, ei, bb->succs)
00750 {
00751 if (e->dest ==
00752 EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
00753 (node->decl)))
00754 fprintf (f, "edge ENTRY -> EXIT, Count");
00755 else
00756 fprintf (f, "edge ENTRY -> %d, Count", e->dest->index);
00757 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
00758 " Prob %d\n", (HOST_WIDE_INT) e->count,
00759 e->probability);
00760 }
00761 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
00762 {
00763 fprintf (f, "bb[%d]: ", bb->index);
00764 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
00765 " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
00766 FOR_EACH_EDGE (e, ei, bb->succs)
00767 {
00768 if (e->dest ==
00769 EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
00770 (node->decl)))
00771 fprintf (f, "edge %d -> EXIT, Count", e->src->index);
00772 else
00773 fprintf (f, "edge %d -> %d, Count", e->src->index,
00774 e->dest->index);
00775 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC " Prob %d\n",
00776 (HOST_WIDE_INT) e->count, e->probability);
00777 }
00778 }
00779 }
00780 }
00781 }
00782
00783
00784 static void
00785 ipcp_profile_bb_print (FILE * f)
00786 {
00787 basic_block bb;
00788 struct cgraph_node *node;
00789
00790 for (node = cgraph_nodes; node; node = node->next)
00791 {
00792 fprintf (f, "method %s: \n", cgraph_node_name (node));
00793 if (DECL_SAVED_TREE (node->decl))
00794 {
00795 bb =
00796 ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
00797 fprintf (f, "ENTRY: Count");
00798 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
00799 " Frquency %d\n", (HOST_WIDE_INT) bb->count,
00800 bb->frequency);
00801
00802 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
00803 {
00804 fprintf (f, "bb[%d]: Count", bb->index);
00805 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
00806 " Frequency %d\n", (HOST_WIDE_INT) bb->count,
00807 bb->frequency);
00808 }
00809 bb =
00810 EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
00811 fprintf (f, "EXIT: Count");
00812 fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
00813 " Frequency %d\n", (HOST_WIDE_INT) bb->count,
00814 bb->frequency);
00815
00816 }
00817 }
00818 }
00819
00820
00821 static void
00822 ipcp_structures_print (FILE * f)
00823 {
00824 ipcp_method_cval_print (f);
00825 ipcp_method_scale_print (f);
00826 ipa_method_tree_print (f);
00827 ipa_method_modify_print (f);
00828 ipcp_callsite_param_print (f);
00829 }
00830
00831
00832 static void
00833 ipcp_profile_print (FILE * f)
00834 {
00835 fprintf (f, "\nNODE COUNTS :\n");
00836 ipcp_profile_mt_count_print (f);
00837 fprintf (f, "\nCS COUNTS stage:\n");
00838 ipcp_profile_cs_count_print (f);
00839 fprintf (f, "\nBB COUNTS and FREQUENCIES :\n");
00840 ipcp_profile_bb_print (f);
00841 fprintf (f, "\nCFG EDGES COUNTS and PROBABILITIES :\n");
00842 ipcp_profile_edge_print (f);
00843 }
00844
00845
00846
00847
00848
00849 static struct ipa_replace_map *
00850 ipcp_replace_map_create (enum cvalue_type type, tree parm_tree,
00851 union parameter_info *cvalue)
00852 {
00853 struct ipa_replace_map *replace_map;
00854 tree const_val;
00855
00856 replace_map = XCNEW (struct ipa_replace_map);
00857 gcc_assert (ipcp_type_is_const (type));
00858 if (type == CONST_VALUE_REF )
00859 {
00860 const_val =
00861 build_const_val (cvalue, type, TREE_TYPE (TREE_TYPE (parm_tree)));
00862 replace_map->old_tree = parm_tree;
00863 replace_map->new_tree = const_val;
00864 replace_map->replace_p = true;
00865 replace_map->ref_p = true;
00866 }
00867 else if (TREE_READONLY (parm_tree) && !TREE_ADDRESSABLE (parm_tree))
00868 {
00869 const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
00870 replace_map->old_tree = parm_tree;
00871 replace_map->new_tree = const_val;
00872 replace_map->replace_p = true;
00873 replace_map->ref_p = false;
00874 }
00875 else
00876 {
00877 replace_map->old_tree = NULL;
00878 replace_map->new_tree = NULL;
00879 replace_map->replace_p = false;
00880 replace_map->ref_p = false;
00881 }
00882
00883 return replace_map;
00884 }
00885
00886
00887
00888 static bool
00889 ipcp_redirect (struct cgraph_edge *cs)
00890 {
00891 struct cgraph_node *caller, *callee, *orig_callee;
00892 int i, count;
00893 struct ipa_jump_func *jump_func;
00894 enum jump_func_type type;
00895 enum cvalue_type cval_type;
00896
00897 caller = cs->caller;
00898 callee = cs->callee;
00899 orig_callee = ipcp_method_orig_node (callee);
00900 count = ipa_method_formal_count (orig_callee);
00901 for (i = 0; i < count; i++)
00902 {
00903 cval_type =
00904 ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i));
00905 if (ipcp_type_is_const (cval_type))
00906 {
00907 jump_func = ipa_callsite_param (cs, i);
00908 type = get_type (jump_func);
00909 if (type != CONST_IPATYPE
00910 && type != CONST_IPATYPE_REF)
00911 return true;
00912 }
00913 }
00914
00915 return false;
00916 }
00917
00918
00919 static void
00920 ipcp_update_callgraph (void)
00921 {
00922 struct cgraph_node *node, *orig_callee;
00923 struct cgraph_edge *cs;
00924
00925 for (node = cgraph_nodes; node; node = node->next)
00926 {
00927
00928 if (ipcp_method_is_cloned (node))
00929 continue;
00930 for (cs = node->callees; cs; cs = cs->next_callee)
00931 if (ipcp_method_is_cloned (cs->callee))
00932 {
00933
00934 orig_callee = ipcp_method_orig_node (cs->callee);
00935 if (ipcp_redirect (cs))
00936 {
00937 cgraph_redirect_edge_callee (cs, orig_callee);
00938 TREE_OPERAND (TREE_OPERAND
00939 (get_call_expr_in (cs->call_stmt), 0), 0) =
00940 orig_callee->decl;
00941 }
00942 }
00943 }
00944 }
00945
00946
00947 static void
00948 ipcp_update_bb_counts (struct cgraph_node *node, gcov_type scale)
00949 {
00950 basic_block bb;
00951
00952 FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
00953 bb->count = bb->count * scale / REG_BR_PROB_BASE;
00954 }
00955
00956
00957 static void
00958 ipcp_update_edges_counts (struct cgraph_node *node, gcov_type scale)
00959 {
00960 basic_block bb;
00961 edge_iterator ei;
00962 edge e;
00963
00964 FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
00965 FOR_EACH_EDGE (e, ei, bb->succs)
00966 e->count = e->count * scale / REG_BR_PROB_BASE;
00967 }
00968
00969
00970
00971 static void
00972 ipcp_update_profiling (void)
00973 {
00974 struct cgraph_node *node, *orig_node;
00975 gcov_type scale, scale_complement;
00976 struct cgraph_edge *cs;
00977
00978 for (node = cgraph_nodes; node; node = node->next)
00979 {
00980 if (ipcp_method_is_cloned (node))
00981 {
00982 orig_node = ipcp_method_orig_node (node);
00983 scale = ipcp_method_get_scale (orig_node);
00984 node->count = orig_node->count * scale / REG_BR_PROB_BASE;
00985 scale_complement = REG_BR_PROB_BASE - scale;
00986 orig_node->count =
00987 orig_node->count * scale_complement / REG_BR_PROB_BASE;
00988 for (cs = node->callees; cs; cs = cs->next_callee)
00989 cs->count = cs->count * scale / REG_BR_PROB_BASE;
00990 for (cs = orig_node->callees; cs; cs = cs->next_callee)
00991 cs->count = cs->count * scale_complement / REG_BR_PROB_BASE;
00992 ipcp_update_bb_counts (node, scale);
00993 ipcp_update_bb_counts (orig_node, scale_complement);
00994 ipcp_update_edges_counts (node, scale);
00995 ipcp_update_edges_counts (orig_node, scale_complement);
00996 }
00997 }
00998 }
00999
01000
01001
01002 static void
01003 ipcp_insert_stage (void)
01004 {
01005 struct cgraph_node *node, *node1 = NULL;
01006 int i, const_param;
01007 union parameter_info *cvalue;
01008 VEC(cgraph_edge_p,heap) *redirect_callers;
01009 varray_type replace_trees;
01010 struct cgraph_edge *cs;
01011 int node_callers, count;
01012 tree parm_tree;
01013 enum cvalue_type type;
01014 struct ipa_replace_map *replace_param;
01015
01016 for (node = cgraph_nodes; node; node = node->next)
01017 {
01018
01019
01020 if (ipcp_method_dont_insert_const (node))
01021 continue;
01022 const_param = 0;
01023 count = ipa_method_formal_count (node);
01024 for (i = 0; i < count; i++)
01025 {
01026 type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
01027 if (ipcp_type_is_const (type))
01028 const_param++;
01029 }
01030 if (const_param == 0)
01031 continue;
01032 VARRAY_GENERIC_PTR_INIT (replace_trees, const_param, "replace_trees");
01033 for (i = 0; i < count; i++)
01034 {
01035 type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
01036 if (ipcp_type_is_const (type))
01037 {
01038 cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
01039 parm_tree = ipa_method_get_tree (node, i);
01040 replace_param =
01041 ipcp_replace_map_create (type, parm_tree, cvalue);
01042 VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param);
01043 }
01044 }
01045
01046 node_callers = 0;
01047 for (cs = node->callers; cs != NULL; cs = cs->next_caller)
01048 node_callers++;
01049 redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers);
01050 for (cs = node->callers; cs != NULL; cs = cs->next_caller)
01051 VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
01052
01053
01054 node1 =
01055 cgraph_function_versioning (node, redirect_callers, replace_trees);
01056 VEC_free (cgraph_edge_p, heap, redirect_callers);
01057 VARRAY_CLEAR (replace_trees);
01058 if (node1 == NULL)
01059 continue;
01060 if (dump_file)
01061 fprintf (dump_file, "versioned function %s\n",
01062 cgraph_node_name (node));
01063 ipcp_cloned_create (node, node1);
01064 for (i = 0; i < count; i++)
01065 {
01066 type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
01067 if (ipcp_type_is_const (type))
01068 {
01069 cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
01070 parm_tree = ipa_method_get_tree (node, i);
01071 if (type != CONST_VALUE_REF
01072 && !TREE_READONLY (parm_tree))
01073 ipcp_propagate_const (node1, i, cvalue, type);
01074 }
01075 }
01076 }
01077 ipcp_update_callgraph ();
01078 ipcp_update_profiling ();
01079 }
01080
01081
01082 unsigned int
01083 ipcp_driver (void)
01084 {
01085 if (dump_file)
01086 fprintf (dump_file, "\nIPA constant propagation start:\n");
01087 ipa_nodes_create ();
01088 ipa_edges_create ();
01089
01090
01091 ipcp_init_stage ();
01092 if (dump_file)
01093 {
01094 fprintf (dump_file, "\nIPA structures before propagation:\n");
01095 ipcp_structures_print (dump_file);
01096 }
01097
01098 ipcp_iterate_stage ();
01099 if (dump_file)
01100 {
01101 fprintf (dump_file, "\nIPA structures after propagation:\n");
01102 ipcp_structures_print (dump_file);
01103 fprintf (dump_file, "\nProfiling info before insert stage:\n");
01104 ipcp_profile_print (dump_file);
01105 }
01106
01107 ipcp_insert_stage ();
01108 if (dump_file)
01109 {
01110 fprintf (dump_file, "\nProfiling info after insert stage:\n");
01111 ipcp_profile_print (dump_file);
01112 }
01113
01114 ipa_free ();
01115 ipa_nodes_free ();
01116 ipa_edges_free ();
01117 if (dump_file)
01118 fprintf (dump_file, "\nIPA constant propagation end\n");
01119 cgraph_remove_unreachable_nodes (true, NULL);
01120 return 0;
01121 }
01122
01123
01124 static bool
01125 cgraph_gate_cp (void)
01126 {
01127 return flag_ipa_cp;
01128 }
01129
01130 struct tree_opt_pass pass_ipa_cp = {
01131 "cp",
01132 cgraph_gate_cp,
01133 ipcp_driver,
01134 NULL,
01135 NULL,
01136 0,
01137 TV_IPA_CONSTANT_PROP,
01138 0,
01139 PROP_trees,
01140 0,
01141 0,
01142 TODO_dump_cgraph | TODO_dump_func,
01143 0
01144 };