Mercurial > hg > CbC > CbC_gcc
comparison gcc/cgraph.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
92 #include "gimple.h" | 92 #include "gimple.h" |
93 #include "tree-dump.h" | 93 #include "tree-dump.h" |
94 #include "tree-flow.h" | 94 #include "tree-flow.h" |
95 #include "value-prof.h" | 95 #include "value-prof.h" |
96 #include "except.h" | 96 #include "except.h" |
97 #include "diagnostic.h" | 97 #include "diagnostic-core.h" |
98 #include "rtl.h" | 98 #include "rtl.h" |
99 #include "ipa-utils.h" | 99 #include "ipa-utils.h" |
100 #include "lto-streamer.h" | |
101 | |
102 const char * const ld_plugin_symbol_resolution_names[]= | |
103 { | |
104 "", | |
105 "undef", | |
106 "prevailing_def", | |
107 "prevailing_def_ironly", | |
108 "preempted_reg", | |
109 "preempted_ir", | |
110 "resolved_ir", | |
111 "resolved_exec", | |
112 "resolved_dyn" | |
113 }; | |
100 | 114 |
101 static void cgraph_node_remove_callers (struct cgraph_node *node); | 115 static void cgraph_node_remove_callers (struct cgraph_node *node); |
102 static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); | 116 static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); |
103 static inline void cgraph_edge_remove_callee (struct cgraph_edge *e); | 117 static inline void cgraph_edge_remove_callee (struct cgraph_edge *e); |
104 | 118 |
148 /* The order index of the next cgraph node to be created. This is | 162 /* The order index of the next cgraph node to be created. This is |
149 used so that we can sort the cgraph nodes in order by when we saw | 163 used so that we can sort the cgraph nodes in order by when we saw |
150 them, to support -fno-toplevel-reorder. */ | 164 them, to support -fno-toplevel-reorder. */ |
151 int cgraph_order; | 165 int cgraph_order; |
152 | 166 |
153 /* List of hooks trigerred on cgraph_edge events. */ | 167 /* List of hooks triggered on cgraph_edge events. */ |
154 struct cgraph_edge_hook_list { | 168 struct cgraph_edge_hook_list { |
155 cgraph_edge_hook hook; | 169 cgraph_edge_hook hook; |
156 void *data; | 170 void *data; |
157 struct cgraph_edge_hook_list *next; | 171 struct cgraph_edge_hook_list *next; |
158 }; | 172 }; |
159 | 173 |
160 /* List of hooks trigerred on cgraph_node events. */ | 174 /* List of hooks triggered on cgraph_node events. */ |
161 struct cgraph_node_hook_list { | 175 struct cgraph_node_hook_list { |
162 cgraph_node_hook hook; | 176 cgraph_node_hook hook; |
163 void *data; | 177 void *data; |
164 struct cgraph_node_hook_list *next; | 178 struct cgraph_node_hook_list *next; |
165 }; | 179 }; |
166 | 180 |
167 /* List of hooks trigerred on events involving two cgraph_edges. */ | 181 /* List of hooks triggered on events involving two cgraph_edges. */ |
168 struct cgraph_2edge_hook_list { | 182 struct cgraph_2edge_hook_list { |
169 cgraph_2edge_hook hook; | 183 cgraph_2edge_hook hook; |
170 void *data; | 184 void *data; |
171 struct cgraph_2edge_hook_list *next; | 185 struct cgraph_2edge_hook_list *next; |
172 }; | 186 }; |
173 | 187 |
174 /* List of hooks trigerred on events involving two cgraph_nodes. */ | 188 /* List of hooks triggered on events involving two cgraph_nodes. */ |
175 struct cgraph_2node_hook_list { | 189 struct cgraph_2node_hook_list { |
176 cgraph_2node_hook hook; | 190 cgraph_2node_hook hook; |
177 void *data; | 191 void *data; |
178 struct cgraph_2node_hook_list *next; | 192 struct cgraph_2node_hook_list *next; |
179 }; | 193 }; |
440 node = free_nodes; | 454 node = free_nodes; |
441 free_nodes = NEXT_FREE_NODE (node); | 455 free_nodes = NEXT_FREE_NODE (node); |
442 } | 456 } |
443 else | 457 else |
444 { | 458 { |
445 node = GGC_CNEW (struct cgraph_node); | 459 node = ggc_alloc_cleared_cgraph_node (); |
446 node->uid = cgraph_max_uid++; | 460 node->uid = cgraph_max_uid++; |
447 } | 461 } |
448 | 462 |
449 return node; | 463 return node; |
450 } | 464 } |
462 if (cgraph_nodes) | 476 if (cgraph_nodes) |
463 cgraph_nodes->previous = node; | 477 cgraph_nodes->previous = node; |
464 node->previous = NULL; | 478 node->previous = NULL; |
465 node->global.estimated_growth = INT_MIN; | 479 node->global.estimated_growth = INT_MIN; |
466 node->frequency = NODE_FREQUENCY_NORMAL; | 480 node->frequency = NODE_FREQUENCY_NORMAL; |
481 node->count_materialization_scale = REG_BR_PROB_BASE; | |
467 ipa_empty_ref_list (&node->ref_list); | 482 ipa_empty_ref_list (&node->ref_list); |
468 cgraph_nodes = node; | 483 cgraph_nodes = node; |
469 cgraph_n_nodes++; | 484 cgraph_n_nodes++; |
470 return node; | 485 return node; |
471 } | 486 } |
519 *aslot = node; | 534 *aslot = node; |
520 } | 535 } |
521 return node; | 536 return node; |
522 } | 537 } |
523 | 538 |
524 /* Mark ALIAS as an alias to DECL. */ | 539 /* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing |
540 the function body is associated with (not neccesarily cgraph_node (DECL). */ | |
525 | 541 |
526 static struct cgraph_node * | 542 static struct cgraph_node * |
527 cgraph_same_body_alias_1 (tree alias, tree decl) | 543 cgraph_same_body_alias_1 (struct cgraph_node *decl_node, tree alias, tree decl) |
528 { | 544 { |
529 struct cgraph_node key, *alias_node, *decl_node, **slot; | 545 struct cgraph_node key, *alias_node, **slot; |
530 | 546 |
531 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); | 547 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); |
532 gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); | 548 gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); |
533 decl_node = cgraph_node (decl); | |
534 | 549 |
535 key.decl = alias; | 550 key.decl = alias; |
536 | 551 |
537 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT); | 552 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT); |
538 | 553 |
552 decl_node->same_body = alias_node; | 567 decl_node->same_body = alias_node; |
553 *slot = alias_node; | 568 *slot = alias_node; |
554 return alias_node; | 569 return alias_node; |
555 } | 570 } |
556 | 571 |
557 /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. | 572 /* Attempt to mark ALIAS as an alias to DECL. Return alias node if successful |
573 and NULL otherwise. | |
558 Same body aliases are output whenever the body of DECL is output, | 574 Same body aliases are output whenever the body of DECL is output, |
559 and cgraph_node (ALIAS) transparently returns cgraph_node (DECL). */ | 575 and cgraph_node (ALIAS) transparently returns cgraph_node (DECL). */ |
560 | 576 |
561 bool | 577 struct cgraph_node * |
562 cgraph_same_body_alias (tree alias, tree decl) | 578 cgraph_same_body_alias (struct cgraph_node *decl_node, tree alias, tree decl) |
563 { | 579 { |
564 #ifndef ASM_OUTPUT_DEF | 580 #ifndef ASM_OUTPUT_DEF |
565 /* If aliases aren't supported by the assembler, fail. */ | 581 /* If aliases aren't supported by the assembler, fail. */ |
566 return false; | 582 return NULL; |
567 #endif | 583 #endif |
568 | 584 |
569 /*gcc_assert (!assembler_name_hash);*/ | 585 /*gcc_assert (!assembler_name_hash);*/ |
570 | 586 |
571 return cgraph_same_body_alias_1 (alias, decl) != NULL; | 587 return cgraph_same_body_alias_1 (decl_node, alias, decl); |
572 } | 588 } |
573 | 589 |
574 void | 590 /* Add thunk alias into callgraph. The alias declaration is ALIAS and it |
575 cgraph_add_thunk (tree alias, tree decl, bool this_adjusting, | 591 aliases DECL with an adjustments made into the first parameter. |
592 See comments in thunk_adjust for detail on the parameters. */ | |
593 | |
594 struct cgraph_node * | |
595 cgraph_add_thunk (struct cgraph_node *decl_node, tree alias, tree decl, | |
596 bool this_adjusting, | |
576 HOST_WIDE_INT fixed_offset, HOST_WIDE_INT virtual_value, | 597 HOST_WIDE_INT fixed_offset, HOST_WIDE_INT virtual_value, |
577 tree virtual_offset, | 598 tree virtual_offset, |
578 tree real_alias) | 599 tree real_alias) |
579 { | 600 { |
580 struct cgraph_node *node = cgraph_get_node (alias); | 601 struct cgraph_node *node = cgraph_get_node (alias); |
584 gcc_assert (node->local.finalized); | 605 gcc_assert (node->local.finalized); |
585 gcc_assert (!node->same_body); | 606 gcc_assert (!node->same_body); |
586 cgraph_remove_node (node); | 607 cgraph_remove_node (node); |
587 } | 608 } |
588 | 609 |
589 node = cgraph_same_body_alias_1 (alias, decl); | 610 node = cgraph_same_body_alias_1 (decl_node, alias, decl); |
590 gcc_assert (node); | 611 gcc_assert (node); |
591 #ifdef ENABLE_CHECKING | 612 gcc_checking_assert (!virtual_offset |
592 gcc_assert (!virtual_offset | 613 || tree_int_cst_equal (virtual_offset, |
593 || tree_int_cst_equal (virtual_offset, size_int (virtual_value))); | 614 size_int (virtual_value))); |
594 #endif | |
595 node->thunk.fixed_offset = fixed_offset; | 615 node->thunk.fixed_offset = fixed_offset; |
596 node->thunk.this_adjusting = this_adjusting; | 616 node->thunk.this_adjusting = this_adjusting; |
597 node->thunk.virtual_value = virtual_value; | 617 node->thunk.virtual_value = virtual_value; |
598 node->thunk.virtual_offset_p = virtual_offset != NULL; | 618 node->thunk.virtual_offset_p = virtual_offset != NULL; |
599 node->thunk.alias = real_alias; | 619 node->thunk.alias = real_alias; |
600 node->thunk.thunk_p = true; | 620 node->thunk.thunk_p = true; |
621 return node; | |
601 } | 622 } |
602 | 623 |
603 /* Returns the cgraph node assigned to DECL or NULL if no cgraph node | 624 /* Returns the cgraph node assigned to DECL or NULL if no cgraph node |
604 is assigned. */ | 625 is assigned. */ |
605 | 626 |
606 struct cgraph_node * | 627 struct cgraph_node * |
607 cgraph_get_node (tree decl) | 628 cgraph_get_node_or_alias (const_tree decl) |
608 { | 629 { |
609 struct cgraph_node key, *node = NULL, **slot; | 630 struct cgraph_node key, *node = NULL, **slot; |
610 | 631 |
611 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); | 632 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); |
612 | 633 |
613 if (!cgraph_hash) | 634 if (!cgraph_hash) |
614 return NULL; | 635 return NULL; |
615 | 636 |
616 key.decl = decl; | 637 key.decl = CONST_CAST2 (tree, const_tree, decl); |
638 | |
639 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, | |
640 NO_INSERT); | |
641 | |
642 if (slot && *slot) | |
643 node = *slot; | |
644 return node; | |
645 } | |
646 | |
647 /* Returns the cgraph node assigned to DECL or NULL if no cgraph node | |
648 is assigned. */ | |
649 | |
650 struct cgraph_node * | |
651 cgraph_get_node (const_tree decl) | |
652 { | |
653 struct cgraph_node key, *node = NULL, **slot; | |
654 | |
655 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); | |
656 | |
657 if (!cgraph_hash) | |
658 return NULL; | |
659 | |
660 key.decl = CONST_CAST2 (tree, const_tree, decl); | |
617 | 661 |
618 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, | 662 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, |
619 NO_INSERT); | 663 NO_INSERT); |
620 | 664 |
621 if (slot && *slot) | 665 if (slot && *slot) |
815 { | 859 { |
816 /* Constant propagation (and possibly also inlining?) can turn an | 860 /* Constant propagation (and possibly also inlining?) can turn an |
817 indirect call into a direct one. */ | 861 indirect call into a direct one. */ |
818 struct cgraph_node *new_callee = cgraph_node (decl); | 862 struct cgraph_node *new_callee = cgraph_node (decl); |
819 | 863 |
820 cgraph_make_edge_direct (e, new_callee); | 864 cgraph_make_edge_direct (e, new_callee, 0); |
821 } | 865 } |
822 | 866 |
823 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); | 867 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); |
824 e->can_throw_external = stmt_can_throw_external (new_stmt); | 868 e->can_throw_external = stmt_can_throw_external (new_stmt); |
825 pop_cfun (); | 869 pop_cfun (); |
892 struct cgraph_edge *edge = cgraph_edge (node, old_stmt); | 936 struct cgraph_edge *edge = cgraph_edge (node, old_stmt); |
893 | 937 |
894 /* It is possible that clones already contain the edge while | 938 /* It is possible that clones already contain the edge while |
895 master didn't. Either we promoted indirect call into direct | 939 master didn't. Either we promoted indirect call into direct |
896 call in the clone or we are processing clones of unreachable | 940 call in the clone or we are processing clones of unreachable |
897 master where edges has been rmeoved. */ | 941 master where edges has been removed. */ |
898 if (edge) | 942 if (edge) |
899 cgraph_set_call_stmt (edge, stmt); | 943 cgraph_set_call_stmt (edge, stmt); |
900 else if (!cgraph_edge (node, stmt)) | 944 else if (!cgraph_edge (node, stmt)) |
901 { | 945 { |
902 edge = cgraph_create_edge (node, callee, stmt, count, | 946 edge = cgraph_create_edge (node, callee, stmt, count, |
952 | 996 |
953 /* LTO does not actually have access to the call_stmt since these | 997 /* LTO does not actually have access to the call_stmt since these |
954 have not been loaded yet. */ | 998 have not been loaded yet. */ |
955 if (call_stmt) | 999 if (call_stmt) |
956 { | 1000 { |
957 #ifdef ENABLE_CHECKING | 1001 /* This is a rather expensive check possibly triggering |
958 /* This is rather pricely check possibly trigerring construction of | 1002 construction of call stmt hashtable. */ |
959 call stmt hashtable. */ | 1003 gcc_checking_assert (!cgraph_edge (caller, call_stmt)); |
960 gcc_assert (!cgraph_edge (caller, call_stmt)); | |
961 #endif | |
962 | 1004 |
963 gcc_assert (is_gimple_call (call_stmt)); | 1005 gcc_assert (is_gimple_call (call_stmt)); |
964 } | 1006 } |
965 | 1007 |
966 if (free_edges) | 1008 if (free_edges) |
968 edge = free_edges; | 1010 edge = free_edges; |
969 free_edges = NEXT_FREE_EDGE (edge); | 1011 free_edges = NEXT_FREE_EDGE (edge); |
970 } | 1012 } |
971 else | 1013 else |
972 { | 1014 { |
973 edge = GGC_NEW (struct cgraph_edge); | 1015 edge = ggc_alloc_cgraph_edge (); |
974 edge->uid = cgraph_edge_max_uid++; | 1016 edge->uid = cgraph_edge_max_uid++; |
975 } | 1017 } |
976 | 1018 |
977 edge->aux = NULL; | 1019 edge->aux = NULL; |
978 edge->caller = caller; | 1020 edge->caller = caller; |
1027 callee->callers = edge; | 1069 callee->callers = edge; |
1028 | 1070 |
1029 return edge; | 1071 return edge; |
1030 } | 1072 } |
1031 | 1073 |
1074 /* Allocate cgraph_indirect_call_info and set its fields to default values. */ | |
1075 | |
1076 struct cgraph_indirect_call_info * | |
1077 cgraph_allocate_init_indirect_info (void) | |
1078 { | |
1079 struct cgraph_indirect_call_info *ii; | |
1080 | |
1081 ii = ggc_alloc_cleared_cgraph_indirect_call_info (); | |
1082 ii->param_index = -1; | |
1083 return ii; | |
1084 } | |
1032 | 1085 |
1033 /* Create an indirect edge with a yet-undetermined callee where the call | 1086 /* Create an indirect edge with a yet-undetermined callee where the call |
1034 statement destination is a formal parameter of the caller with index | 1087 statement destination is a formal parameter of the caller with index |
1035 PARAM_INDEX. */ | 1088 PARAM_INDEX. */ |
1036 | 1089 |
1043 count, freq, nest); | 1096 count, freq, nest); |
1044 | 1097 |
1045 edge->indirect_unknown_callee = 1; | 1098 edge->indirect_unknown_callee = 1; |
1046 initialize_inline_failed (edge); | 1099 initialize_inline_failed (edge); |
1047 | 1100 |
1048 edge->indirect_info = GGC_CNEW (struct cgraph_indirect_call_info); | 1101 edge->indirect_info = cgraph_allocate_init_indirect_info (); |
1049 edge->indirect_info->param_index = -1; | |
1050 edge->indirect_info->ecf_flags = ecf_flags; | 1102 edge->indirect_info->ecf_flags = ecf_flags; |
1051 | 1103 |
1052 edge->next_callee = caller->indirect_calls; | 1104 edge->next_callee = caller->indirect_calls; |
1053 if (caller->indirect_calls) | 1105 if (caller->indirect_calls) |
1054 caller->indirect_calls->prev_callee = edge; | 1106 caller->indirect_calls->prev_callee = edge; |
1152 /* Insert to callers list of the new callee. */ | 1204 /* Insert to callers list of the new callee. */ |
1153 cgraph_set_edge_callee (e, n); | 1205 cgraph_set_edge_callee (e, n); |
1154 } | 1206 } |
1155 | 1207 |
1156 /* Make an indirect EDGE with an unknown callee an ordinary edge leading to | 1208 /* Make an indirect EDGE with an unknown callee an ordinary edge leading to |
1157 CALLEE. */ | 1209 CALLEE. DELTA is an integer constant that is to be added to the this |
1158 | 1210 pointer (first parameter) to compensate for skipping a thunk adjustment. */ |
1159 void | 1211 |
1160 cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee) | 1212 void |
1213 cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee, | |
1214 HOST_WIDE_INT delta) | |
1161 { | 1215 { |
1162 edge->indirect_unknown_callee = 0; | 1216 edge->indirect_unknown_callee = 0; |
1217 edge->indirect_info->thunk_delta = delta; | |
1163 | 1218 |
1164 /* Get the edge out of the indirect edge list. */ | 1219 /* Get the edge out of the indirect edge list. */ |
1165 if (edge->prev_callee) | 1220 if (edge->prev_callee) |
1166 edge->prev_callee->next_callee = edge->next_callee; | 1221 edge->prev_callee->next_callee = edge->next_callee; |
1167 if (edge->next_callee) | 1222 if (edge->next_callee) |
1196 | 1251 |
1197 /* We are seeing indirect calls, then there is nothing to update. */ | 1252 /* We are seeing indirect calls, then there is nothing to update. */ |
1198 if (!new_call && !old_call) | 1253 if (!new_call && !old_call) |
1199 return; | 1254 return; |
1200 /* See if we turned indirect call into direct call or folded call to one builtin | 1255 /* See if we turned indirect call into direct call or folded call to one builtin |
1201 into different bultin. */ | 1256 into different builtin. */ |
1202 if (old_call != new_call) | 1257 if (old_call != new_call) |
1203 { | 1258 { |
1204 struct cgraph_edge *e = cgraph_edge (node, old_stmt); | 1259 struct cgraph_edge *e = cgraph_edge (node, old_stmt); |
1205 struct cgraph_edge *ne = NULL; | 1260 struct cgraph_edge *ne = NULL; |
1206 gcov_type count; | 1261 gcov_type count; |
1209 | 1264 |
1210 if (e) | 1265 if (e) |
1211 { | 1266 { |
1212 /* See if the edge is already there and has the correct callee. It | 1267 /* See if the edge is already there and has the correct callee. It |
1213 might be so because of indirect inlining has already updated | 1268 might be so because of indirect inlining has already updated |
1214 it. */ | 1269 it. We also might've cloned and redirected the edge. */ |
1215 if (new_call && e->callee && e->callee->decl == new_call) | 1270 if (new_call && e->callee) |
1216 return; | 1271 { |
1272 struct cgraph_node *callee = e->callee; | |
1273 while (callee) | |
1274 { | |
1275 if (callee->decl == new_call | |
1276 || callee->former_clone_of == new_call) | |
1277 return; | |
1278 callee = callee->clone_of; | |
1279 } | |
1280 } | |
1217 | 1281 |
1218 /* Otherwise remove edge and create new one; we can't simply redirect | 1282 /* Otherwise remove edge and create new one; we can't simply redirect |
1219 since function has changed, so inline plan and other information | 1283 since function has changed, so inline plan and other information |
1220 attached to edge is invalid. */ | 1284 attached to edge is invalid. */ |
1221 count = e->count; | 1285 count = e->count; |
1657 if (cgraph_global_info_ready) | 1721 if (cgraph_global_info_ready) |
1658 { | 1722 { |
1659 /* Verify that function does not appear to be needed out of blue | 1723 /* Verify that function does not appear to be needed out of blue |
1660 during the optimization process. This can happen for extern | 1724 during the optimization process. This can happen for extern |
1661 inlines when bodies was removed after inlining. */ | 1725 inlines when bodies was removed after inlining. */ |
1662 gcc_assert ((node->analyzed || DECL_EXTERNAL (node->decl))); | 1726 gcc_assert ((node->analyzed || node->in_other_partition |
1727 || DECL_EXTERNAL (node->decl))); | |
1663 } | 1728 } |
1664 else | 1729 else |
1665 notice_global_symbol (node->decl); | 1730 notice_global_symbol (node->decl); |
1666 node->reachable = 1; | 1731 node->reachable = 1; |
1667 | 1732 |
1684 /* Likewise indicate that a node is having address taken. */ | 1749 /* Likewise indicate that a node is having address taken. */ |
1685 | 1750 |
1686 void | 1751 void |
1687 cgraph_mark_address_taken_node (struct cgraph_node *node) | 1752 cgraph_mark_address_taken_node (struct cgraph_node *node) |
1688 { | 1753 { |
1754 gcc_assert (!node->global.inlined_to); | |
1689 cgraph_mark_reachable_node (node); | 1755 cgraph_mark_reachable_node (node); |
1690 node->address_taken = 1; | 1756 node->address_taken = 1; |
1691 } | 1757 } |
1692 | 1758 |
1693 /* Return local info for the compiled function. */ | 1759 /* Return local info for the compiled function. */ |
1774 fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))); | 1840 fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))); |
1775 if (node->global.inlined_to) | 1841 if (node->global.inlined_to) |
1776 fprintf (f, " (inline copy in %s/%i)", | 1842 fprintf (f, " (inline copy in %s/%i)", |
1777 cgraph_node_name (node->global.inlined_to), | 1843 cgraph_node_name (node->global.inlined_to), |
1778 node->global.inlined_to->uid); | 1844 node->global.inlined_to->uid); |
1845 if (node->same_comdat_group) | |
1846 fprintf (f, " (same comdat group as %s/%i)", | |
1847 cgraph_node_name (node->same_comdat_group), | |
1848 node->same_comdat_group->uid); | |
1779 if (node->clone_of) | 1849 if (node->clone_of) |
1780 fprintf (f, " (clone of %s/%i)", | 1850 fprintf (f, " (clone of %s/%i)", |
1781 cgraph_node_name (node->clone_of), | 1851 cgraph_node_name (node->clone_of), |
1782 node->clone_of->uid); | 1852 node->clone_of->uid); |
1783 if (cgraph_function_flags_ready) | 1853 if (cgraph_function_flags_ready) |
1822 fprintf (f, " process"); | 1892 fprintf (f, " process"); |
1823 if (node->local.local) | 1893 if (node->local.local) |
1824 fprintf (f, " local"); | 1894 fprintf (f, " local"); |
1825 if (node->local.externally_visible) | 1895 if (node->local.externally_visible) |
1826 fprintf (f, " externally_visible"); | 1896 fprintf (f, " externally_visible"); |
1897 if (node->resolution != LDPR_UNKNOWN) | |
1898 fprintf (f, " %s", | |
1899 ld_plugin_symbol_resolution_names[(int)node->resolution]); | |
1827 if (node->local.finalized) | 1900 if (node->local.finalized) |
1828 fprintf (f, " finalized"); | 1901 fprintf (f, " finalized"); |
1829 if (node->local.disregard_inline_limits) | 1902 if (node->local.disregard_inline_limits) |
1830 fprintf (f, " always_inline"); | 1903 fprintf (f, " always_inline"); |
1831 else if (node->local.inlinable) | 1904 else if (node->local.inlinable) |
1834 fprintf (f, " versionable"); | 1907 fprintf (f, " versionable"); |
1835 if (node->local.redefined_extern_inline) | 1908 if (node->local.redefined_extern_inline) |
1836 fprintf (f, " redefined_extern_inline"); | 1909 fprintf (f, " redefined_extern_inline"); |
1837 if (TREE_ASM_WRITTEN (node->decl)) | 1910 if (TREE_ASM_WRITTEN (node->decl)) |
1838 fprintf (f, " asm_written"); | 1911 fprintf (f, " asm_written"); |
1912 if (node->only_called_at_startup) | |
1913 fprintf (f, " only_called_at_startup"); | |
1914 if (node->only_called_at_exit) | |
1915 fprintf (f, " only_called_at_exit"); | |
1839 | 1916 |
1840 fprintf (f, "\n called by: "); | 1917 fprintf (f, "\n called by: "); |
1841 for (edge = node->callers; edge; edge = edge->next_caller) | 1918 for (edge = node->callers; edge; edge = edge->next_caller) |
1842 { | 1919 { |
1843 fprintf (f, "%s/%i ", cgraph_node_name (edge->caller), | 1920 fprintf (f, "%s/%i ", cgraph_node_name (edge->caller), |
1895 for (n = node->same_body; n; n = n->next) | 1972 for (n = node->same_body; n; n = n->next) |
1896 { | 1973 { |
1897 fprintf (f, " %s/%i", cgraph_node_name (n), n->uid); | 1974 fprintf (f, " %s/%i", cgraph_node_name (n), n->uid); |
1898 if (n->thunk.thunk_p) | 1975 if (n->thunk.thunk_p) |
1899 { | 1976 { |
1900 fprintf (f, " (thunk of %s fixed ofset %i virtual value %i has " | 1977 fprintf (f, " (thunk of %s fixed offset %i virtual value %i has " |
1901 "virtual offset %i", | 1978 "virtual offset %i", |
1902 lang_hooks.decl_printable_name (n->thunk.alias, 2), | 1979 lang_hooks.decl_printable_name (n->thunk.alias, 2), |
1903 (int)n->thunk.fixed_offset, | 1980 (int)n->thunk.fixed_offset, |
1904 (int)n->thunk.virtual_value, | 1981 (int)n->thunk.virtual_value, |
1905 (int)n->thunk.virtual_offset_p); | 1982 (int)n->thunk.virtual_offset_p); |
1913 } | 1990 } |
1914 | 1991 |
1915 | 1992 |
1916 /* Dump call graph node NODE to stderr. */ | 1993 /* Dump call graph node NODE to stderr. */ |
1917 | 1994 |
1918 void | 1995 DEBUG_FUNCTION void |
1919 debug_cgraph_node (struct cgraph_node *node) | 1996 debug_cgraph_node (struct cgraph_node *node) |
1920 { | 1997 { |
1921 dump_cgraph_node (stderr, node); | 1998 dump_cgraph_node (stderr, node); |
1922 } | 1999 } |
1923 | 2000 |
1935 } | 2012 } |
1936 | 2013 |
1937 | 2014 |
1938 /* Dump the call graph to stderr. */ | 2015 /* Dump the call graph to stderr. */ |
1939 | 2016 |
1940 void | 2017 DEBUG_FUNCTION void |
1941 debug_cgraph (void) | 2018 debug_cgraph (void) |
1942 { | 2019 { |
1943 dump_cgraph (stderr); | 2020 dump_cgraph (stderr); |
1944 } | 2021 } |
1945 | 2022 |
1947 /* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables. */ | 2024 /* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables. */ |
1948 | 2025 |
1949 void | 2026 void |
1950 change_decl_assembler_name (tree decl, tree name) | 2027 change_decl_assembler_name (tree decl, tree name) |
1951 { | 2028 { |
1952 gcc_assert (!assembler_name_hash); | 2029 struct cgraph_node *node; |
2030 void **slot; | |
1953 if (!DECL_ASSEMBLER_NAME_SET_P (decl)) | 2031 if (!DECL_ASSEMBLER_NAME_SET_P (decl)) |
1954 { | 2032 SET_DECL_ASSEMBLER_NAME (decl, name); |
2033 else | |
2034 { | |
2035 if (name == DECL_ASSEMBLER_NAME (decl)) | |
2036 return; | |
2037 | |
2038 if (assembler_name_hash | |
2039 && TREE_CODE (decl) == FUNCTION_DECL | |
2040 && (node = cgraph_get_node_or_alias (decl)) != NULL) | |
2041 { | |
2042 tree old_name = DECL_ASSEMBLER_NAME (decl); | |
2043 slot = htab_find_slot_with_hash (assembler_name_hash, old_name, | |
2044 decl_assembler_name_hash (old_name), | |
2045 NO_INSERT); | |
2046 /* Inline clones are not hashed. */ | |
2047 if (slot && *slot == node) | |
2048 htab_clear_slot (assembler_name_hash, slot); | |
2049 } | |
2050 if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) | |
2051 && DECL_RTL_SET_P (decl)) | |
2052 warning (0, "%D renamed after being referenced in assembly", decl); | |
2053 | |
1955 SET_DECL_ASSEMBLER_NAME (decl, name); | 2054 SET_DECL_ASSEMBLER_NAME (decl, name); |
1956 return; | 2055 } |
1957 } | 2056 if (assembler_name_hash |
1958 if (name == DECL_ASSEMBLER_NAME (decl)) | 2057 && TREE_CODE (decl) == FUNCTION_DECL |
1959 return; | 2058 && (node = cgraph_get_node_or_alias (decl)) != NULL) |
1960 | 2059 { |
1961 if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) | 2060 slot = htab_find_slot_with_hash (assembler_name_hash, name, |
1962 && DECL_RTL_SET_P (decl)) | 2061 decl_assembler_name_hash (name), |
1963 warning (0, "%D renamed after being referenced in assembly", decl); | 2062 INSERT); |
1964 | 2063 gcc_assert (!*slot); |
1965 SET_DECL_ASSEMBLER_NAME (decl, name); | 2064 *slot = node; |
2065 } | |
1966 } | 2066 } |
1967 | 2067 |
1968 /* Add a top-level asm statement to the list. */ | 2068 /* Add a top-level asm statement to the list. */ |
1969 | 2069 |
1970 struct cgraph_asm_node * | 2070 struct cgraph_asm_node * |
1971 cgraph_add_asm_node (tree asm_str) | 2071 cgraph_add_asm_node (tree asm_str) |
1972 { | 2072 { |
1973 struct cgraph_asm_node *node; | 2073 struct cgraph_asm_node *node; |
1974 | 2074 |
1975 node = GGC_CNEW (struct cgraph_asm_node); | 2075 node = ggc_alloc_cleared_cgraph_asm_node (); |
1976 node->asm_str = asm_str; | 2076 node->asm_str = asm_str; |
1977 node->order = cgraph_order++; | 2077 node->order = cgraph_order++; |
1978 node->next = NULL; | 2078 node->next = NULL; |
1979 if (cgraph_asm_nodes == NULL) | 2079 if (cgraph_asm_nodes == NULL) |
1980 cgraph_asm_nodes = node; | 2080 cgraph_asm_nodes = node; |
2028 e->loop_nest + loop_nest); | 2128 e->loop_nest + loop_nest); |
2029 *new_edge->indirect_info = *e->indirect_info; | 2129 *new_edge->indirect_info = *e->indirect_info; |
2030 } | 2130 } |
2031 } | 2131 } |
2032 else | 2132 else |
2033 new_edge = cgraph_create_edge (n, e->callee, call_stmt, count, freq, | 2133 { |
2034 e->loop_nest + loop_nest); | 2134 new_edge = cgraph_create_edge (n, e->callee, call_stmt, count, freq, |
2135 e->loop_nest + loop_nest); | |
2136 if (e->indirect_info) | |
2137 { | |
2138 new_edge->indirect_info | |
2139 = ggc_alloc_cleared_cgraph_indirect_call_info (); | |
2140 *new_edge->indirect_info = *e->indirect_info; | |
2141 } | |
2142 } | |
2035 | 2143 |
2036 new_edge->inline_failed = e->inline_failed; | 2144 new_edge->inline_failed = e->inline_failed; |
2037 new_edge->indirect_inlining_edge = e->indirect_inlining_edge; | 2145 new_edge->indirect_inlining_edge = e->indirect_inlining_edge; |
2038 new_edge->lto_stmt_uid = stmt_uid; | 2146 new_edge->lto_stmt_uid = stmt_uid; |
2147 /* Clone flags that depend on call_stmt availability manually. */ | |
2148 new_edge->can_throw_external = e->can_throw_external; | |
2149 new_edge->call_stmt_cannot_inline_p = e->call_stmt_cannot_inline_p; | |
2039 if (update_original) | 2150 if (update_original) |
2040 { | 2151 { |
2041 e->count -= new_edge->count; | 2152 e->count -= new_edge->count; |
2042 if (e->count < 0) | 2153 if (e->count < 0) |
2043 e->count = 0; | 2154 e->count = 0; |
2096 n->count -= count; | 2207 n->count -= count; |
2097 if (n->count < 0) | 2208 if (n->count < 0) |
2098 n->count = 0; | 2209 n->count = 0; |
2099 } | 2210 } |
2100 | 2211 |
2101 for (i = 0; VEC_iterate (cgraph_edge_p, redirect_callers, i, e); i++) | 2212 FOR_EACH_VEC_ELT (cgraph_edge_p, redirect_callers, i, e) |
2102 { | 2213 { |
2103 /* Redirect calls to the old version node to point to its new | 2214 /* Redirect calls to the old version node to point to its new |
2104 version. */ | 2215 version. */ |
2105 cgraph_redirect_edge_callee (e, new_node); | 2216 cgraph_redirect_edge_callee (e, new_node); |
2106 } | 2217 } |
2141 } | 2252 } |
2142 } | 2253 } |
2143 return new_node; | 2254 return new_node; |
2144 } | 2255 } |
2145 | 2256 |
2146 /* Create a new name for omp child function. Returns an identifier. */ | 2257 /* Create a new name for clone of DECL, add SUFFIX. Returns an identifier. */ |
2147 | 2258 |
2148 static GTY(()) unsigned int clone_fn_id_num; | 2259 static GTY(()) unsigned int clone_fn_id_num; |
2149 | 2260 |
2150 static tree | 2261 tree |
2151 clone_function_name (tree decl) | 2262 clone_function_name (tree decl, const char *suffix) |
2152 { | 2263 { |
2153 tree name = DECL_ASSEMBLER_NAME (decl); | 2264 tree name = DECL_ASSEMBLER_NAME (decl); |
2154 size_t len = IDENTIFIER_LENGTH (name); | 2265 size_t len = IDENTIFIER_LENGTH (name); |
2155 char *tmp_name, *prefix; | 2266 char *tmp_name, *prefix; |
2156 | 2267 |
2157 prefix = XALLOCAVEC (char, len + strlen ("_clone") + 1); | 2268 prefix = XALLOCAVEC (char, len + strlen (suffix) + 2); |
2158 memcpy (prefix, IDENTIFIER_POINTER (name), len); | 2269 memcpy (prefix, IDENTIFIER_POINTER (name), len); |
2159 strcpy (prefix + len, "_clone"); | 2270 strcpy (prefix + len + 1, suffix); |
2160 #ifndef NO_DOT_IN_LABEL | 2271 #ifndef NO_DOT_IN_LABEL |
2161 prefix[len] = '.'; | 2272 prefix[len] = '.'; |
2162 #elif !defined NO_DOLLAR_IN_LABEL | 2273 #elif !defined NO_DOLLAR_IN_LABEL |
2163 prefix[len] = '$'; | 2274 prefix[len] = '$'; |
2275 #else | |
2276 prefix[len] = '_'; | |
2164 #endif | 2277 #endif |
2165 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++); | 2278 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++); |
2166 return get_identifier (tmp_name); | 2279 return get_identifier (tmp_name); |
2167 } | 2280 } |
2168 | 2281 |
2174 */ | 2287 */ |
2175 struct cgraph_node * | 2288 struct cgraph_node * |
2176 cgraph_create_virtual_clone (struct cgraph_node *old_node, | 2289 cgraph_create_virtual_clone (struct cgraph_node *old_node, |
2177 VEC(cgraph_edge_p,heap) *redirect_callers, | 2290 VEC(cgraph_edge_p,heap) *redirect_callers, |
2178 VEC(ipa_replace_map_p,gc) *tree_map, | 2291 VEC(ipa_replace_map_p,gc) *tree_map, |
2179 bitmap args_to_skip) | 2292 bitmap args_to_skip, |
2293 const char * suffix) | |
2180 { | 2294 { |
2181 tree old_decl = old_node->decl; | 2295 tree old_decl = old_node->decl; |
2182 struct cgraph_node *new_node = NULL; | 2296 struct cgraph_node *new_node = NULL; |
2183 tree new_decl; | 2297 tree new_decl; |
2184 size_t i; | 2298 size_t i; |
2185 struct ipa_replace_map *map; | 2299 struct ipa_replace_map *map; |
2186 | 2300 |
2187 #ifdef ENABLE_CHECKING | |
2188 if (!flag_wpa) | 2301 if (!flag_wpa) |
2189 gcc_assert (tree_versionable_function_p (old_decl)); | 2302 gcc_checking_assert (tree_versionable_function_p (old_decl)); |
2190 #endif | 2303 |
2304 gcc_assert (old_node->local.can_change_signature || !args_to_skip); | |
2191 | 2305 |
2192 /* Make a new FUNCTION_DECL tree node */ | 2306 /* Make a new FUNCTION_DECL tree node */ |
2193 if (!args_to_skip) | 2307 if (!args_to_skip) |
2194 new_decl = copy_node (old_decl); | 2308 new_decl = copy_node (old_decl); |
2195 else | 2309 else |
2196 new_decl = build_function_decl_skip_args (old_decl, args_to_skip); | 2310 new_decl = build_function_decl_skip_args (old_decl, args_to_skip); |
2197 DECL_STRUCT_FUNCTION (new_decl) = NULL; | 2311 DECL_STRUCT_FUNCTION (new_decl) = NULL; |
2198 | 2312 |
2199 /* Generate a new name for the new version. */ | 2313 /* Generate a new name for the new version. */ |
2200 DECL_NAME (new_decl) = clone_function_name (old_decl); | 2314 DECL_NAME (new_decl) = clone_function_name (old_decl, suffix); |
2201 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | 2315 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); |
2202 SET_DECL_RTL (new_decl, NULL); | 2316 SET_DECL_RTL (new_decl, NULL); |
2203 | 2317 |
2204 new_node = cgraph_clone_node (old_node, new_decl, old_node->count, | 2318 new_node = cgraph_clone_node (old_node, new_decl, old_node->count, |
2205 CGRAPH_FREQ_BASE, 0, false, | 2319 CGRAPH_FREQ_BASE, 0, false, |
2208 Make clone visible only within this translation unit. Make sure | 2322 Make clone visible only within this translation unit. Make sure |
2209 that is not weak also. | 2323 that is not weak also. |
2210 ??? We cannot use COMDAT linkage because there is no | 2324 ??? We cannot use COMDAT linkage because there is no |
2211 ABI support for this. */ | 2325 ABI support for this. */ |
2212 DECL_EXTERNAL (new_node->decl) = 0; | 2326 DECL_EXTERNAL (new_node->decl) = 0; |
2327 if (DECL_ONE_ONLY (old_decl)) | |
2328 DECL_SECTION_NAME (new_node->decl) = NULL; | |
2213 DECL_COMDAT_GROUP (new_node->decl) = 0; | 2329 DECL_COMDAT_GROUP (new_node->decl) = 0; |
2214 TREE_PUBLIC (new_node->decl) = 0; | 2330 TREE_PUBLIC (new_node->decl) = 0; |
2215 DECL_COMDAT (new_node->decl) = 0; | 2331 DECL_COMDAT (new_node->decl) = 0; |
2216 DECL_WEAK (new_node->decl) = 0; | 2332 DECL_WEAK (new_node->decl) = 0; |
2217 new_node->clone.tree_map = tree_map; | 2333 new_node->clone.tree_map = tree_map; |
2218 new_node->clone.args_to_skip = args_to_skip; | 2334 new_node->clone.args_to_skip = args_to_skip; |
2219 for (i = 0; VEC_iterate (ipa_replace_map_p, tree_map, i, map); i++) | 2335 FOR_EACH_VEC_ELT (ipa_replace_map_p, tree_map, i, map) |
2220 { | 2336 { |
2221 tree var = map->new_tree; | 2337 tree var = map->new_tree; |
2222 | 2338 |
2223 STRIP_NOPS (var); | 2339 STRIP_NOPS (var); |
2224 if (TREE_CODE (var) != ADDR_EXPR) | 2340 if (TREE_CODE (var) != ADDR_EXPR) |
2244 tree arg; | 2360 tree arg; |
2245 bitmap new_args_to_skip = BITMAP_GGC_ALLOC (); | 2361 bitmap new_args_to_skip = BITMAP_GGC_ALLOC (); |
2246 struct cgraph_node *orig_node; | 2362 struct cgraph_node *orig_node; |
2247 for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of) | 2363 for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of) |
2248 ; | 2364 ; |
2249 for (arg = DECL_ARGUMENTS (orig_node->decl); arg; arg = TREE_CHAIN (arg), oldi++) | 2365 for (arg = DECL_ARGUMENTS (orig_node->decl); arg; arg = DECL_CHAIN (arg), oldi++) |
2250 { | 2366 { |
2251 if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi)) | 2367 if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi)) |
2252 { | 2368 { |
2253 bitmap_set_bit (new_args_to_skip, oldi); | 2369 bitmap_set_bit (new_args_to_skip, oldi); |
2254 continue; | 2370 continue; |
2294 avail = AVAIL_NOT_AVAILABLE; | 2410 avail = AVAIL_NOT_AVAILABLE; |
2295 else if (node->local.local) | 2411 else if (node->local.local) |
2296 avail = AVAIL_LOCAL; | 2412 avail = AVAIL_LOCAL; |
2297 else if (!node->local.externally_visible) | 2413 else if (!node->local.externally_visible) |
2298 avail = AVAIL_AVAILABLE; | 2414 avail = AVAIL_AVAILABLE; |
2299 /* Inline functions are safe to be analyzed even if their sybol can | 2415 /* Inline functions are safe to be analyzed even if their symbol can |
2300 be overwritten at runtime. It is not meaningful to enfore any sane | 2416 be overwritten at runtime. It is not meaningful to enforce any sane |
2301 behaviour on replacing inline function by different body. */ | 2417 behaviour on replacing inline function by different body. */ |
2302 else if (DECL_DECLARED_INLINE_P (node->decl)) | 2418 else if (DECL_DECLARED_INLINE_P (node->decl)) |
2303 avail = AVAIL_AVAILABLE; | 2419 avail = AVAIL_AVAILABLE; |
2304 | 2420 |
2305 /* If the function can be overwritten, return OVERWRITABLE. Take | 2421 /* If the function can be overwritten, return OVERWRITABLE. Take |
2310 | 2426 |
2311 ??? Does the C++ one definition rule allow us to always return | 2427 ??? Does the C++ one definition rule allow us to always return |
2312 AVAIL_AVAILABLE here? That would be good reason to preserve this | 2428 AVAIL_AVAILABLE here? That would be good reason to preserve this |
2313 bit. */ | 2429 bit. */ |
2314 | 2430 |
2315 else if (DECL_REPLACEABLE_P (node->decl) && !DECL_EXTERNAL (node->decl)) | 2431 else if (decl_replaceable_p (node->decl) && !DECL_EXTERNAL (node->decl)) |
2316 avail = AVAIL_OVERWRITABLE; | 2432 avail = AVAIL_OVERWRITABLE; |
2317 else avail = AVAIL_AVAILABLE; | 2433 else avail = AVAIL_AVAILABLE; |
2318 | 2434 |
2319 return avail; | 2435 return avail; |
2320 } | 2436 } |
2420 { | 2536 { |
2421 rtx rtl, symbol; | 2537 rtx rtl, symbol; |
2422 | 2538 |
2423 if (TREE_CODE (decl) == VAR_DECL) | 2539 if (TREE_CODE (decl) == VAR_DECL) |
2424 DECL_COMMON (decl) = 0; | 2540 DECL_COMMON (decl) = 0; |
2425 else if (TREE_CODE (decl) == FUNCTION_DECL) | 2541 else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); |
2426 { | 2542 |
2543 if (DECL_COMDAT (decl)) | |
2544 { | |
2545 /* It is possible that we are linking against library defining same COMDAT | |
2546 function. To avoid conflict we need to rename our local name of the | |
2547 function just in the case WHOPR partitioning decide to make it hidden | |
2548 to avoid cross partition references. */ | |
2549 if (flag_wpa) | |
2550 { | |
2551 const char *old_name; | |
2552 | |
2553 old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
2554 if (TREE_CODE (decl) == FUNCTION_DECL) | |
2555 { | |
2556 struct cgraph_node *node = cgraph_get_node_or_alias (decl); | |
2557 change_decl_assembler_name (decl, | |
2558 clone_function_name (decl, "local")); | |
2559 if (node->local.lto_file_data) | |
2560 lto_record_renamed_decl (node->local.lto_file_data, | |
2561 old_name, | |
2562 IDENTIFIER_POINTER | |
2563 (DECL_ASSEMBLER_NAME (decl))); | |
2564 } | |
2565 else if (TREE_CODE (decl) == VAR_DECL) | |
2566 { | |
2567 struct varpool_node *vnode = varpool_get_node (decl); | |
2568 /* change_decl_assembler_name will warn here on vtables because | |
2569 C++ frontend still sets TREE_SYMBOL_REFERENCED on them. */ | |
2570 SET_DECL_ASSEMBLER_NAME (decl, | |
2571 clone_function_name (decl, "local")); | |
2572 if (vnode->lto_file_data) | |
2573 lto_record_renamed_decl (vnode->lto_file_data, | |
2574 old_name, | |
2575 IDENTIFIER_POINTER | |
2576 (DECL_ASSEMBLER_NAME (decl))); | |
2577 } | |
2578 } | |
2579 DECL_SECTION_NAME (decl) = 0; | |
2427 DECL_COMDAT (decl) = 0; | 2580 DECL_COMDAT (decl) = 0; |
2428 DECL_COMDAT_GROUP (decl) = 0; | 2581 } |
2429 DECL_WEAK (decl) = 0; | 2582 DECL_COMDAT_GROUP (decl) = 0; |
2430 DECL_EXTERNAL (decl) = 0; | 2583 DECL_WEAK (decl) = 0; |
2431 } | 2584 DECL_EXTERNAL (decl) = 0; |
2432 else | |
2433 gcc_unreachable (); | |
2434 TREE_PUBLIC (decl) = 0; | 2585 TREE_PUBLIC (decl) = 0; |
2435 if (!DECL_RTL_SET_P (decl)) | 2586 if (!DECL_RTL_SET_P (decl)) |
2436 return; | 2587 return; |
2437 | 2588 |
2438 /* Update rtl flags. */ | 2589 /* Update rtl flags. */ |
2462 for (alias = node->same_body; alias; alias = alias->next) | 2613 for (alias = node->same_body; alias; alias = alias->next) |
2463 cgraph_make_decl_local (alias->decl); | 2614 cgraph_make_decl_local (alias->decl); |
2464 | 2615 |
2465 node->local.externally_visible = false; | 2616 node->local.externally_visible = false; |
2466 node->local.local = true; | 2617 node->local.local = true; |
2618 node->resolution = LDPR_PREVAILING_DEF_IRONLY; | |
2467 gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL); | 2619 gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL); |
2468 } | 2620 } |
2469 } | 2621 } |
2470 | 2622 |
2471 /* Set TREE_NOTHROW on NODE's decl and on same_body aliases of NODE | 2623 /* Set TREE_NOTHROW on NODE's decl and on same_body aliases of NODE |
2482 | 2634 |
2483 /* Set TREE_READONLY on NODE's decl and on same_body aliases of NODE | 2635 /* Set TREE_READONLY on NODE's decl and on same_body aliases of NODE |
2484 if any to READONLY. */ | 2636 if any to READONLY. */ |
2485 | 2637 |
2486 void | 2638 void |
2487 cgraph_set_readonly_flag (struct cgraph_node *node, bool readonly) | 2639 cgraph_set_const_flag (struct cgraph_node *node, bool readonly, bool looping) |
2488 { | 2640 { |
2489 struct cgraph_node *alias; | 2641 struct cgraph_node *alias; |
2642 /* Static constructors and destructors without a side effect can be | |
2643 optimized out. */ | |
2644 if (!looping && readonly) | |
2645 { | |
2646 if (DECL_STATIC_CONSTRUCTOR (node->decl)) | |
2647 DECL_STATIC_CONSTRUCTOR (node->decl) = 0; | |
2648 if (DECL_STATIC_DESTRUCTOR (node->decl)) | |
2649 DECL_STATIC_DESTRUCTOR (node->decl) = 0; | |
2650 } | |
2490 TREE_READONLY (node->decl) = readonly; | 2651 TREE_READONLY (node->decl) = readonly; |
2652 DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping; | |
2491 for (alias = node->same_body; alias; alias = alias->next) | 2653 for (alias = node->same_body; alias; alias = alias->next) |
2492 TREE_READONLY (alias->decl) = readonly; | 2654 { |
2655 TREE_READONLY (alias->decl) = readonly; | |
2656 DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping; | |
2657 } | |
2493 } | 2658 } |
2494 | 2659 |
2495 /* Set DECL_PURE_P on NODE's decl and on same_body aliases of NODE | 2660 /* Set DECL_PURE_P on NODE's decl and on same_body aliases of NODE |
2496 if any to PURE. */ | 2661 if any to PURE. */ |
2497 | 2662 |
2498 void | 2663 void |
2499 cgraph_set_pure_flag (struct cgraph_node *node, bool pure) | 2664 cgraph_set_pure_flag (struct cgraph_node *node, bool pure, bool looping) |
2500 { | 2665 { |
2501 struct cgraph_node *alias; | 2666 struct cgraph_node *alias; |
2667 /* Static constructors and destructors without a side effect can be | |
2668 optimized out. */ | |
2669 if (!looping && pure) | |
2670 { | |
2671 if (DECL_STATIC_CONSTRUCTOR (node->decl)) | |
2672 DECL_STATIC_CONSTRUCTOR (node->decl) = 0; | |
2673 if (DECL_STATIC_DESTRUCTOR (node->decl)) | |
2674 DECL_STATIC_DESTRUCTOR (node->decl) = 0; | |
2675 } | |
2502 DECL_PURE_P (node->decl) = pure; | 2676 DECL_PURE_P (node->decl) = pure; |
2677 DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping; | |
2503 for (alias = node->same_body; alias; alias = alias->next) | 2678 for (alias = node->same_body; alias; alias = alias->next) |
2504 DECL_PURE_P (alias->decl) = pure; | 2679 { |
2505 } | 2680 DECL_PURE_P (alias->decl) = pure; |
2506 | 2681 DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping; |
2507 /* Set DECL_LOOPING_CONST_OR_PURE_P on NODE's decl and on | 2682 } |
2508 same_body aliases of NODE if any to LOOPING_CONST_OR_PURE. */ | |
2509 | |
2510 void | |
2511 cgraph_set_looping_const_or_pure_flag (struct cgraph_node *node, | |
2512 bool looping_const_or_pure) | |
2513 { | |
2514 struct cgraph_node *alias; | |
2515 DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping_const_or_pure; | |
2516 for (alias = node->same_body; alias; alias = alias->next) | |
2517 DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping_const_or_pure; | |
2518 } | 2683 } |
2519 | 2684 |
2520 /* See if the frequency of NODE can be updated based on frequencies of its | 2685 /* See if the frequency of NODE can be updated based on frequencies of its |
2521 callers. */ | 2686 callers. */ |
2522 bool | 2687 bool |
2523 cgraph_propagate_frequency (struct cgraph_node *node) | 2688 cgraph_propagate_frequency (struct cgraph_node *node) |
2524 { | 2689 { |
2525 bool maybe_unlikely_executed = true, maybe_executed_once = true; | 2690 bool maybe_unlikely_executed = true, maybe_executed_once = true; |
2691 bool only_called_at_startup = true; | |
2692 bool only_called_at_exit = true; | |
2693 bool changed = false; | |
2526 struct cgraph_edge *edge; | 2694 struct cgraph_edge *edge; |
2695 | |
2527 if (!node->local.local) | 2696 if (!node->local.local) |
2528 return false; | 2697 return false; |
2529 gcc_assert (node->analyzed); | 2698 gcc_assert (node->analyzed); |
2530 if (node->frequency == NODE_FREQUENCY_HOT) | |
2531 return false; | |
2532 if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED) | |
2533 return false; | |
2534 if (dump_file && (dump_flags & TDF_DETAILS)) | 2699 if (dump_file && (dump_flags & TDF_DETAILS)) |
2535 fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node)); | 2700 fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node)); |
2701 | |
2536 for (edge = node->callers; | 2702 for (edge = node->callers; |
2537 edge && (maybe_unlikely_executed || maybe_executed_once); | 2703 edge && (maybe_unlikely_executed || maybe_executed_once |
2704 || only_called_at_startup || only_called_at_exit); | |
2538 edge = edge->next_caller) | 2705 edge = edge->next_caller) |
2539 { | 2706 { |
2707 if (edge->caller != node) | |
2708 { | |
2709 only_called_at_startup &= edge->caller->only_called_at_startup; | |
2710 /* It makes sense to put main() together with the static constructors. | |
2711 It will be executed for sure, but rest of functions called from | |
2712 main are definitely not at startup only. */ | |
2713 if (MAIN_NAME_P (DECL_NAME (edge->caller->decl))) | |
2714 only_called_at_startup = 0; | |
2715 only_called_at_exit &= edge->caller->only_called_at_exit; | |
2716 } | |
2540 if (!edge->frequency) | 2717 if (!edge->frequency) |
2541 continue; | 2718 continue; |
2542 switch (edge->caller->frequency) | 2719 switch (edge->caller->frequency) |
2543 { | 2720 { |
2544 case NODE_FREQUENCY_UNLIKELY_EXECUTED: | 2721 case NODE_FREQUENCY_UNLIKELY_EXECUTED: |
2545 break; | 2722 break; |
2546 case NODE_FREQUENCY_EXECUTED_ONCE: | 2723 case NODE_FREQUENCY_EXECUTED_ONCE: |
2547 if (dump_file && (dump_flags & TDF_DETAILS)) | 2724 if (dump_file && (dump_flags & TDF_DETAILS)) |
2548 fprintf (dump_file, " Called by %s that is executed once\n", cgraph_node_name (node)); | 2725 fprintf (dump_file, " Called by %s that is executed once\n", |
2726 cgraph_node_name (edge->caller)); | |
2549 maybe_unlikely_executed = false; | 2727 maybe_unlikely_executed = false; |
2550 if (edge->loop_nest) | 2728 if (edge->loop_nest) |
2551 { | 2729 { |
2552 maybe_executed_once = false; | 2730 maybe_executed_once = false; |
2553 if (dump_file && (dump_flags & TDF_DETAILS)) | 2731 if (dump_file && (dump_flags & TDF_DETAILS)) |
2555 } | 2733 } |
2556 break; | 2734 break; |
2557 case NODE_FREQUENCY_HOT: | 2735 case NODE_FREQUENCY_HOT: |
2558 case NODE_FREQUENCY_NORMAL: | 2736 case NODE_FREQUENCY_NORMAL: |
2559 if (dump_file && (dump_flags & TDF_DETAILS)) | 2737 if (dump_file && (dump_flags & TDF_DETAILS)) |
2560 fprintf (dump_file, " Called by %s that is normal or hot\n", cgraph_node_name (node)); | 2738 fprintf (dump_file, " Called by %s that is normal or hot\n", |
2739 cgraph_node_name (edge->caller)); | |
2561 maybe_unlikely_executed = false; | 2740 maybe_unlikely_executed = false; |
2562 maybe_executed_once = false; | 2741 maybe_executed_once = false; |
2563 break; | 2742 break; |
2564 } | 2743 } |
2565 } | 2744 } |
2566 if (maybe_unlikely_executed) | 2745 if ((only_called_at_startup && !only_called_at_exit) |
2567 { | 2746 && !node->only_called_at_startup) |
2568 node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED; | 2747 { |
2748 node->only_called_at_startup = true; | |
2569 if (dump_file) | 2749 if (dump_file) |
2570 fprintf (dump_file, "Node %s promoted to unlikely executed.\n", cgraph_node_name (node)); | 2750 fprintf (dump_file, "Node %s promoted to only called at startup.\n", |
2571 return true; | 2751 cgraph_node_name (node)); |
2572 } | 2752 changed = true; |
2573 if (maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE) | 2753 } |
2574 { | 2754 if ((only_called_at_exit && !only_called_at_startup) |
2575 node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; | 2755 && !node->only_called_at_exit) |
2756 { | |
2757 node->only_called_at_exit = true; | |
2576 if (dump_file) | 2758 if (dump_file) |
2577 fprintf (dump_file, "Node %s promoted to executed once.\n", cgraph_node_name (node)); | 2759 fprintf (dump_file, "Node %s promoted to only called at exit.\n", |
2578 return true; | 2760 cgraph_node_name (node)); |
2579 } | 2761 changed = true; |
2580 return false; | 2762 } |
2763 /* These come either from profile or user hints; never update them. */ | |
2764 if (node->frequency == NODE_FREQUENCY_HOT | |
2765 || node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED) | |
2766 return changed; | |
2767 if (maybe_unlikely_executed) | |
2768 { | |
2769 node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED; | |
2770 if (dump_file) | |
2771 fprintf (dump_file, "Node %s promoted to unlikely executed.\n", | |
2772 cgraph_node_name (node)); | |
2773 changed = true; | |
2774 } | |
2775 else if (maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE) | |
2776 { | |
2777 node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; | |
2778 if (dump_file) | |
2779 fprintf (dump_file, "Node %s promoted to executed once.\n", | |
2780 cgraph_node_name (node)); | |
2781 changed = true; | |
2782 } | |
2783 return changed; | |
2784 } | |
2785 | |
2786 /* Return true when NODE can not return or throw and thus | |
2787 it is safe to ignore its side effects for IPA analysis. */ | |
2788 | |
2789 bool | |
2790 cgraph_node_cannot_return (struct cgraph_node *node) | |
2791 { | |
2792 int flags = flags_from_decl_or_type (node->decl); | |
2793 if (!flag_exceptions) | |
2794 return (flags & ECF_NORETURN) != 0; | |
2795 else | |
2796 return ((flags & (ECF_NORETURN | ECF_NOTHROW)) | |
2797 == (ECF_NORETURN | ECF_NOTHROW)); | |
2798 } | |
2799 | |
2800 /* Return true when call of E can not lead to return from caller | |
2801 and thus it is safe to ignore its side effects for IPA analysis | |
2802 when computing side effects of the caller. | |
2803 FIXME: We could actually mark all edges that have no reaching | |
2804 patch to EXIT_BLOCK_PTR or throw to get better results. */ | |
2805 bool | |
2806 cgraph_edge_cannot_lead_to_return (struct cgraph_edge *e) | |
2807 { | |
2808 if (cgraph_node_cannot_return (e->caller)) | |
2809 return true; | |
2810 if (e->indirect_unknown_callee) | |
2811 { | |
2812 int flags = e->indirect_info->ecf_flags; | |
2813 if (!flag_exceptions) | |
2814 return (flags & ECF_NORETURN) != 0; | |
2815 else | |
2816 return ((flags & (ECF_NORETURN | ECF_NOTHROW)) | |
2817 == (ECF_NORETURN | ECF_NOTHROW)); | |
2818 } | |
2819 else | |
2820 return cgraph_node_cannot_return (e->callee); | |
2821 } | |
2822 | |
2823 /* Return true when function NODE can be removed from callgraph | |
2824 if all direct calls are eliminated. */ | |
2825 | |
2826 bool | |
2827 cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) | |
2828 { | |
2829 gcc_assert (!node->global.inlined_to); | |
2830 /* Extern inlines can always go, we will use the external definition. */ | |
2831 if (DECL_EXTERNAL (node->decl)) | |
2832 return true; | |
2833 /* When function is needed, we can not remove it. */ | |
2834 if (node->needed || node->reachable_from_other_partition) | |
2835 return false; | |
2836 if (DECL_STATIC_CONSTRUCTOR (node->decl) | |
2837 || DECL_STATIC_DESTRUCTOR (node->decl)) | |
2838 return false; | |
2839 /* Only COMDAT functions can be removed if externally visible. */ | |
2840 if (node->local.externally_visible | |
2841 && (!DECL_COMDAT (node->decl) | |
2842 || cgraph_used_from_object_file_p (node))) | |
2843 return false; | |
2844 return true; | |
2845 } | |
2846 | |
2847 /* Return true when function NODE can be expected to be removed | |
2848 from program when direct calls in this compilation unit are removed. | |
2849 | |
2850 As a special case COMDAT functions are | |
2851 cgraph_can_remove_if_no_direct_calls_p while the are not | |
2852 cgraph_only_called_directly_p (it is possible they are called from other | |
2853 unit) | |
2854 | |
2855 This function behaves as cgraph_only_called_directly_p because eliminating | |
2856 all uses of COMDAT function does not make it necessarily disappear from | |
2857 the program unless we are compiling whole program or we do LTO. In this | |
2858 case we know we win since dynamic linking will not really discard the | |
2859 linkonce section. */ | |
2860 | |
2861 bool | |
2862 cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node) | |
2863 { | |
2864 gcc_assert (!node->global.inlined_to); | |
2865 if (cgraph_used_from_object_file_p (node)) | |
2866 return false; | |
2867 if (!in_lto_p && !flag_whole_program) | |
2868 return cgraph_only_called_directly_p (node); | |
2869 else | |
2870 { | |
2871 if (DECL_EXTERNAL (node->decl)) | |
2872 return true; | |
2873 return cgraph_can_remove_if_no_direct_calls_p (node); | |
2874 } | |
2875 } | |
2876 | |
2877 /* Return true when RESOLUTION indicate that linker will use | |
2878 the symbol from non-LTO object files. */ | |
2879 | |
2880 bool | |
2881 resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution) | |
2882 { | |
2883 return (resolution == LDPR_PREVAILING_DEF | |
2884 || resolution == LDPR_PREEMPTED_REG | |
2885 || resolution == LDPR_RESOLVED_EXEC | |
2886 || resolution == LDPR_RESOLVED_DYN); | |
2887 } | |
2888 | |
2889 /* Return true when NODE is known to be used from other (non-LTO) object file. | |
2890 Known only when doing LTO via linker plugin. */ | |
2891 | |
2892 bool | |
2893 cgraph_used_from_object_file_p (struct cgraph_node *node) | |
2894 { | |
2895 struct cgraph_node *alias; | |
2896 | |
2897 gcc_assert (!node->global.inlined_to); | |
2898 if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) | |
2899 return false; | |
2900 if (resolution_used_from_other_file_p (node->resolution)) | |
2901 return true; | |
2902 for (alias = node->same_body; alias; alias = alias->next) | |
2903 if (TREE_PUBLIC (alias->decl) | |
2904 && resolution_used_from_other_file_p (alias->resolution)) | |
2905 return true; | |
2906 return false; | |
2581 } | 2907 } |
2582 | 2908 |
2583 #include "gt-cgraph.h" | 2909 #include "gt-cgraph.h" |