Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-cp.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Interprocedural constant propagation | 1 /* Interprocedural constant propagation |
2 Copyright (C) 2005-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2005-2020 Free Software Foundation, Inc. |
3 | 3 |
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor | 4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor |
5 <mjambor@suse.cz> | 5 <mjambor@suse.cz> |
6 | 6 |
7 This file is part of GCC. | 7 This file is part of GCC. |
116 #include "symbol-summary.h" | 116 #include "symbol-summary.h" |
117 #include "tree-vrp.h" | 117 #include "tree-vrp.h" |
118 #include "ipa-prop.h" | 118 #include "ipa-prop.h" |
119 #include "tree-pretty-print.h" | 119 #include "tree-pretty-print.h" |
120 #include "tree-inline.h" | 120 #include "tree-inline.h" |
121 #include "params.h" | |
122 #include "ipa-fnsummary.h" | 121 #include "ipa-fnsummary.h" |
123 #include "ipa-utils.h" | 122 #include "ipa-utils.h" |
124 #include "tree-ssa-ccp.h" | 123 #include "tree-ssa-ccp.h" |
125 #include "stringpool.h" | 124 #include "stringpool.h" |
126 #include "attribs.h" | 125 #include "attribs.h" |
128 template <typename valtype> class ipcp_value; | 127 template <typename valtype> class ipcp_value; |
129 | 128 |
130 /* Describes a particular source for an IPA-CP value. */ | 129 /* Describes a particular source for an IPA-CP value. */ |
131 | 130 |
132 template <typename valtype> | 131 template <typename valtype> |
133 class ipcp_value_source | 132 struct ipcp_value_source |
134 { | 133 { |
135 public: | 134 public: |
136 /* Aggregate offset of the source, negative if the source is scalar value of | 135 /* Aggregate offset of the source, negative if the source is scalar value of |
137 the argument itself. */ | 136 the argument itself. */ |
138 HOST_WIDE_INT offset; | 137 HOST_WIDE_INT offset; |
189 created. */ | 188 created. */ |
190 cgraph_node *spec_node; | 189 cgraph_node *spec_node; |
191 /* Depth first search number and low link for topological sorting of | 190 /* Depth first search number and low link for topological sorting of |
192 values. */ | 191 values. */ |
193 int dfs, low_link; | 192 int dfs, low_link; |
194 /* True if this valye is currently on the topo-sort stack. */ | 193 /* True if this value is currently on the topo-sort stack. */ |
195 bool on_stack; | 194 bool on_stack; |
196 | 195 |
197 ipcp_value() | 196 ipcp_value() |
198 : sources (0), next (0), scc_next (0), topo_next (0), | 197 : sources (0), next (0), scc_next (0), topo_next (0), |
199 spec_node (0), dfs (0), low_link (0), on_stack (false) {} | 198 spec_node (0), dfs (0), low_link (0), on_stack (false) {} |
207 and with contains_variable and bottom flags cleared. BOTTOM is represented | 206 and with contains_variable and bottom flags cleared. BOTTOM is represented |
208 by a lattice with the bottom flag set. In that case, values and | 207 by a lattice with the bottom flag set. In that case, values and |
209 contains_variable flag should be disregarded. */ | 208 contains_variable flag should be disregarded. */ |
210 | 209 |
211 template <typename valtype> | 210 template <typename valtype> |
212 class ipcp_lattice | 211 struct ipcp_lattice |
213 { | 212 { |
214 public: | 213 public: |
215 /* The list of known values and types in this lattice. Note that values are | 214 /* The list of known values and types in this lattice. Note that values are |
216 not deallocated if a lattice is set to bottom because there may be value | 215 not deallocated if a lattice is set to bottom because there may be value |
217 sources referencing them. */ | 216 sources referencing them. */ |
227 inline bool is_single_const (); | 226 inline bool is_single_const (); |
228 inline bool set_to_bottom (); | 227 inline bool set_to_bottom (); |
229 inline bool set_contains_variable (); | 228 inline bool set_contains_variable (); |
230 bool add_value (valtype newval, cgraph_edge *cs, | 229 bool add_value (valtype newval, cgraph_edge *cs, |
231 ipcp_value<valtype> *src_val = NULL, | 230 ipcp_value<valtype> *src_val = NULL, |
232 int src_idx = 0, HOST_WIDE_INT offset = -1); | 231 int src_idx = 0, HOST_WIDE_INT offset = -1, |
232 ipcp_value<valtype> **val_p = NULL, | |
233 bool unlimited = false); | |
233 void print (FILE * f, bool dump_sources, bool dump_benefits); | 234 void print (FILE * f, bool dump_sources, bool dump_benefits); |
234 }; | 235 }; |
235 | 236 |
236 /* Lattice of tree values with an offset to describe a part of an | 237 /* Lattice of tree values with an offset to describe a part of an |
237 aggregate. */ | 238 aggregate. */ |
238 | 239 |
239 class ipcp_agg_lattice : public ipcp_lattice<tree> | 240 struct ipcp_agg_lattice : public ipcp_lattice<tree> |
240 { | 241 { |
241 public: | 242 public: |
242 /* Offset that is being described by this lattice. */ | 243 /* Offset that is being described by this lattice. */ |
243 HOST_WIDE_INT offset; | 244 HOST_WIDE_INT offset; |
244 /* Size so that we don't have to re-compute it every time we traverse the | 245 /* Size so that we don't have to re-compute it every time we traverse the |
372 | 373 |
373 static profile_count max_count; | 374 static profile_count max_count; |
374 | 375 |
375 /* Original overall size of the program. */ | 376 /* Original overall size of the program. */ |
376 | 377 |
377 static long overall_size, max_new_size; | 378 static long overall_size, orig_overall_size; |
379 | |
380 /* Node name to unique clone suffix number map. */ | |
381 static hash_map<const char *, unsigned> *clone_num_suffixes; | |
378 | 382 |
379 /* Return the param lattices structure corresponding to the Ith formal | 383 /* Return the param lattices structure corresponding to the Ith formal |
380 parameter of the function described by INFO. */ | 384 parameter of the function described by INFO. */ |
381 static inline struct ipcp_param_lattices * | 385 static inline class ipcp_param_lattices * |
382 ipa_get_parm_lattices (struct ipa_node_params *info, int i) | 386 ipa_get_parm_lattices (class ipa_node_params *info, int i) |
383 { | 387 { |
384 gcc_assert (i >= 0 && i < ipa_get_param_count (info)); | 388 gcc_assert (i >= 0 && i < ipa_get_param_count (info)); |
385 gcc_checking_assert (!info->ipcp_orig_node); | 389 gcc_checking_assert (!info->ipcp_orig_node); |
386 gcc_checking_assert (info->lattices); | 390 gcc_checking_assert (info->lattices); |
387 return &(info->lattices[i]); | 391 return &(info->lattices[i]); |
388 } | 392 } |
389 | 393 |
390 /* Return the lattice corresponding to the scalar value of the Ith formal | 394 /* Return the lattice corresponding to the scalar value of the Ith formal |
391 parameter of the function described by INFO. */ | 395 parameter of the function described by INFO. */ |
392 static inline ipcp_lattice<tree> * | 396 static inline ipcp_lattice<tree> * |
393 ipa_get_scalar_lat (struct ipa_node_params *info, int i) | 397 ipa_get_scalar_lat (class ipa_node_params *info, int i) |
394 { | 398 { |
395 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 399 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
396 return &plats->itself; | 400 return &plats->itself; |
397 } | 401 } |
398 | 402 |
399 /* Return the lattice corresponding to the scalar value of the Ith formal | 403 /* Return the lattice corresponding to the scalar value of the Ith formal |
400 parameter of the function described by INFO. */ | 404 parameter of the function described by INFO. */ |
401 static inline ipcp_lattice<ipa_polymorphic_call_context> * | 405 static inline ipcp_lattice<ipa_polymorphic_call_context> * |
402 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i) | 406 ipa_get_poly_ctx_lat (class ipa_node_params *info, int i) |
403 { | 407 { |
404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 408 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
405 return &plats->ctxlat; | 409 return &plats->ctxlat; |
406 } | 410 } |
407 | 411 |
408 /* Return whether LAT is a lattice with a single constant and without an | 412 /* Return whether LAT is a lattice with a single constant and without an |
409 undefined value. */ | 413 undefined value. */ |
534 int i, count; | 538 int i, count; |
535 | 539 |
536 fprintf (f, "\nLattices:\n"); | 540 fprintf (f, "\nLattices:\n"); |
537 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | 541 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) |
538 { | 542 { |
539 struct ipa_node_params *info; | 543 class ipa_node_params *info; |
540 | 544 |
541 info = IPA_NODE_REF (node); | 545 info = IPA_NODE_REF (node); |
546 /* Skip unoptimized functions and constprop clones since we don't make | |
547 lattices for them. */ | |
548 if (!info || info->ipcp_orig_node) | |
549 continue; | |
542 fprintf (f, " Node: %s:\n", node->dump_name ()); | 550 fprintf (f, " Node: %s:\n", node->dump_name ()); |
543 count = ipa_get_param_count (info); | 551 count = ipa_get_param_count (info); |
544 for (i = 0; i < count; i++) | 552 for (i = 0; i < count; i++) |
545 { | 553 { |
546 struct ipcp_agg_lattice *aglat; | 554 struct ipcp_agg_lattice *aglat; |
547 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 555 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
548 fprintf (f, " param [%d]: ", i); | 556 fprintf (f, " param [%d]: ", i); |
549 plats->itself.print (f, dump_sources, dump_benefits); | 557 plats->itself.print (f, dump_sources, dump_benefits); |
550 fprintf (f, " ctxs: "); | 558 fprintf (f, " ctxs: "); |
551 plats->ctxlat.print (f, dump_sources, dump_benefits); | 559 plats->ctxlat.print (f, dump_sources, dump_benefits); |
552 plats->bits_lattice.print (f); | 560 plats->bits_lattice.print (f); |
577 and store this information in the ipa_node_params structure associated | 585 and store this information in the ipa_node_params structure associated |
578 with NODE. */ | 586 with NODE. */ |
579 | 587 |
580 static void | 588 static void |
581 determine_versionability (struct cgraph_node *node, | 589 determine_versionability (struct cgraph_node *node, |
582 struct ipa_node_params *info) | 590 class ipa_node_params *info) |
583 { | 591 { |
584 const char *reason = NULL; | 592 const char *reason = NULL; |
585 | 593 |
586 /* There are a number of generic reasons functions cannot be versioned. We | 594 /* There are a number of generic reasons functions cannot be versioned. We |
587 also cannot remove parameters if there are type attributes such as fnspec | 595 also cannot remove parameters if there are type attributes such as fnspec |
588 present. */ | 596 present. */ |
589 if (node->alias || node->thunk.thunk_p) | 597 if (node->alias || node->thunk.thunk_p) |
590 reason = "alias or thunk"; | 598 reason = "alias or thunk"; |
591 else if (!node->local.versionable) | 599 else if (!node->versionable) |
592 reason = "not a tree_versionable_function"; | 600 reason = "not a tree_versionable_function"; |
593 else if (node->get_availability () <= AVAIL_INTERPOSABLE) | 601 else if (node->get_availability () <= AVAIL_INTERPOSABLE) |
594 reason = "insufficient body availability"; | 602 reason = "insufficient body availability"; |
595 else if (!opt_for_fn (node->decl, optimize) | 603 else if (!opt_for_fn (node->decl, optimize) |
596 || !opt_for_fn (node->decl, flag_ipa_cp)) | 604 || !opt_for_fn (node->decl, flag_ipa_cp)) |
648 NODE. */ | 656 NODE. */ |
649 | 657 |
650 static bool | 658 static bool |
651 ipcp_versionable_function_p (struct cgraph_node *node) | 659 ipcp_versionable_function_p (struct cgraph_node *node) |
652 { | 660 { |
653 return IPA_NODE_REF (node)->versionable; | 661 return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable; |
654 } | 662 } |
655 | 663 |
656 /* Structure holding accumulated information about callers of a node. */ | 664 /* Structure holding accumulated information about callers of a node. */ |
657 | 665 |
658 struct caller_statistics | 666 struct caller_statistics |
707 if (!opt_for_fn (node->decl, flag_ipa_cp_clone)) | 715 if (!opt_for_fn (node->decl, flag_ipa_cp_clone)) |
708 { | 716 { |
709 if (dump_file) | 717 if (dump_file) |
710 fprintf (dump_file, "Not considering %s for cloning; " | 718 fprintf (dump_file, "Not considering %s for cloning; " |
711 "-fipa-cp-clone disabled.\n", | 719 "-fipa-cp-clone disabled.\n", |
712 node->name ()); | 720 node->dump_name ()); |
713 return false; | 721 return false; |
714 } | 722 } |
715 | 723 |
716 if (node->optimize_for_size_p ()) | 724 if (node->optimize_for_size_p ()) |
717 { | 725 { |
718 if (dump_file) | 726 if (dump_file) |
719 fprintf (dump_file, "Not considering %s for cloning; " | 727 fprintf (dump_file, "Not considering %s for cloning; " |
720 "optimizing it for size.\n", | 728 "optimizing it for size.\n", |
721 node->name ()); | 729 node->dump_name ()); |
722 return false; | 730 return false; |
723 } | 731 } |
724 | 732 |
725 init_caller_stats (&stats); | 733 init_caller_stats (&stats); |
726 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false); | 734 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false); |
727 | 735 |
728 if (ipa_fn_summaries->get (node)->self_size < stats.n_calls) | 736 if (ipa_size_summaries->get (node)->self_size < stats.n_calls) |
729 { | 737 { |
730 if (dump_file) | 738 if (dump_file) |
731 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n", | 739 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n", |
732 node->name ()); | 740 node->dump_name ()); |
733 return true; | 741 return true; |
734 } | 742 } |
735 | 743 |
736 /* When profile is available and function is hot, propagate into it even if | 744 /* When profile is available and function is hot, propagate into it even if |
737 calls seems cold; constant propagation can improve function's speed | 745 calls seems cold; constant propagation can improve function's speed |
741 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100)) | 749 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100)) |
742 { | 750 { |
743 if (dump_file) | 751 if (dump_file) |
744 fprintf (dump_file, "Considering %s for cloning; " | 752 fprintf (dump_file, "Considering %s for cloning; " |
745 "usually called directly.\n", | 753 "usually called directly.\n", |
746 node->name ()); | 754 node->dump_name ()); |
747 return true; | 755 return true; |
748 } | 756 } |
749 } | 757 } |
750 if (!stats.n_hot_calls) | 758 if (!stats.n_hot_calls) |
751 { | 759 { |
752 if (dump_file) | 760 if (dump_file) |
753 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n", | 761 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n", |
754 node->name ()); | 762 node->dump_name ()); |
755 return false; | 763 return false; |
756 } | 764 } |
757 if (dump_file) | 765 if (dump_file) |
758 fprintf (dump_file, "Considering %s for cloning.\n", | 766 fprintf (dump_file, "Considering %s for cloning.\n", |
759 node->name ()); | 767 node->dump_name ()); |
760 return true; | 768 return true; |
761 } | 769 } |
762 | 770 |
763 template <typename valtype> | 771 template <typename valtype> |
764 class value_topo_info | 772 class value_topo_info |
798 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0), | 806 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0), |
799 constants () | 807 constants () |
800 {} | 808 {} |
801 }; | 809 }; |
802 | 810 |
811 /* Skip edges from and to nodes without ipa_cp enabled. | |
812 Ignore not available symbols. */ | |
813 | |
814 static bool | |
815 ignore_edge_p (cgraph_edge *e) | |
816 { | |
817 enum availability avail; | |
818 cgraph_node *ultimate_target | |
819 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); | |
820 | |
821 return (avail <= AVAIL_INTERPOSABLE | |
822 || !opt_for_fn (ultimate_target->decl, optimize) | |
823 || !opt_for_fn (ultimate_target->decl, flag_ipa_cp)); | |
824 } | |
825 | |
803 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */ | 826 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */ |
804 | 827 |
805 static void | 828 static void |
806 build_toporder_info (struct ipa_topo_info *topo) | 829 build_toporder_info (class ipa_topo_info *topo) |
807 { | 830 { |
808 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); | 831 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); |
809 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); | 832 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); |
810 | 833 |
811 gcc_checking_assert (topo->stack_top == 0); | 834 gcc_checking_assert (topo->stack_top == 0); |
812 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL); | 835 topo->nnodes = ipa_reduced_postorder (topo->order, true, |
836 ignore_edge_p); | |
813 } | 837 } |
814 | 838 |
815 /* Free information about strongly connected components and the arrays in | 839 /* Free information about strongly connected components and the arrays in |
816 TOPO. */ | 840 TOPO. */ |
817 | 841 |
818 static void | 842 static void |
819 free_toporder_info (struct ipa_topo_info *topo) | 843 free_toporder_info (class ipa_topo_info *topo) |
820 { | 844 { |
821 ipa_free_postorder_info (); | 845 ipa_free_postorder_info (); |
822 free (topo->order); | 846 free (topo->order); |
823 free (topo->stack); | 847 free (topo->stack); |
824 } | 848 } |
825 | 849 |
826 /* Add NODE to the stack in TOPO, unless it is already there. */ | 850 /* Add NODE to the stack in TOPO, unless it is already there. */ |
827 | 851 |
828 static inline void | 852 static inline void |
829 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node) | 853 push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node) |
830 { | 854 { |
831 struct ipa_node_params *info = IPA_NODE_REF (node); | 855 class ipa_node_params *info = IPA_NODE_REF (node); |
832 if (info->node_enqueued) | 856 if (info->node_enqueued) |
833 return; | 857 return; |
834 info->node_enqueued = 1; | 858 info->node_enqueued = 1; |
835 topo->stack[topo->stack_top++] = node; | 859 topo->stack[topo->stack_top++] = node; |
836 } | 860 } |
837 | 861 |
838 /* Pop a node from the stack in TOPO and return it or return NULL if the stack | 862 /* Pop a node from the stack in TOPO and return it or return NULL if the stack |
839 is empty. */ | 863 is empty. */ |
840 | 864 |
841 static struct cgraph_node * | 865 static struct cgraph_node * |
842 pop_node_from_stack (struct ipa_topo_info *topo) | 866 pop_node_from_stack (class ipa_topo_info *topo) |
843 { | 867 { |
844 if (topo->stack_top) | 868 if (topo->stack_top) |
845 { | 869 { |
846 struct cgraph_node *node; | 870 struct cgraph_node *node; |
847 topo->stack_top--; | 871 topo->stack_top--; |
875 bool ret = !contains_variable; | 899 bool ret = !contains_variable; |
876 contains_variable = true; | 900 contains_variable = true; |
877 return ret; | 901 return ret; |
878 } | 902 } |
879 | 903 |
880 /* Set all aggegate lattices in PLATS to bottom and return true if they were | 904 /* Set all aggregate lattices in PLATS to bottom and return true if they were |
881 not previously set as such. */ | 905 not previously set as such. */ |
882 | 906 |
883 static inline bool | 907 static inline bool |
884 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats) | 908 set_agg_lats_to_bottom (class ipcp_param_lattices *plats) |
885 { | 909 { |
886 bool ret = !plats->aggs_bottom; | 910 bool ret = !plats->aggs_bottom; |
887 plats->aggs_bottom = true; | 911 plats->aggs_bottom = true; |
888 return ret; | 912 return ret; |
889 } | 913 } |
890 | 914 |
891 /* Mark all aggegate lattices in PLATS as containing an unknown value and | 915 /* Mark all aggregate lattices in PLATS as containing an unknown value and |
892 return true if they were not previously marked as such. */ | 916 return true if they were not previously marked as such. */ |
893 | 917 |
894 static inline bool | 918 static inline bool |
895 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats) | 919 set_agg_lats_contain_variable (class ipcp_param_lattices *plats) |
896 { | 920 { |
897 bool ret = !plats->aggs_contain_variable; | 921 bool ret = !plats->aggs_contain_variable; |
898 plats->aggs_contain_variable = true; | 922 plats->aggs_contain_variable = true; |
899 return ret; | 923 return ret; |
900 } | 924 } |
903 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other) | 927 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other) |
904 { | 928 { |
905 return meet_with_1 (&other.m_vr); | 929 return meet_with_1 (&other.m_vr); |
906 } | 930 } |
907 | 931 |
908 /* Meet the current value of the lattice with value ranfge described by VR | 932 /* Meet the current value of the lattice with value range described by VR |
909 lattice. */ | 933 lattice. */ |
910 | 934 |
911 bool | 935 bool |
912 ipcp_vr_lattice::meet_with (const value_range *p_vr) | 936 ipcp_vr_lattice::meet_with (const value_range *p_vr) |
913 { | 937 { |
926 if (other_vr->varying_p ()) | 950 if (other_vr->varying_p ()) |
927 return set_to_bottom (); | 951 return set_to_bottom (); |
928 | 952 |
929 value_range save (m_vr); | 953 value_range save (m_vr); |
930 m_vr.union_ (other_vr); | 954 m_vr.union_ (other_vr); |
931 return !m_vr.ignore_equivs_equal_p (save); | 955 return !m_vr.equal_p (save); |
932 } | 956 } |
933 | 957 |
934 /* Return true if value range information in the lattice is yet unknown. */ | 958 /* Return true if value range information in the lattice is yet unknown. */ |
935 | 959 |
936 bool | 960 bool |
954 bool | 978 bool |
955 ipcp_vr_lattice::set_to_bottom () | 979 ipcp_vr_lattice::set_to_bottom () |
956 { | 980 { |
957 if (m_vr.varying_p ()) | 981 if (m_vr.varying_p ()) |
958 return false; | 982 return false; |
959 m_vr.set_varying (); | 983 /* ?? We create all sorts of VARYING ranges for floats, structures, |
984 and other types which we cannot handle as ranges. We should | |
985 probably avoid handling them throughout the pass, but it's easier | |
986 to create a sensible VARYING here and let the lattice | |
987 propagate. */ | |
988 m_vr.set_varying (integer_type_node); | |
960 return true; | 989 return true; |
961 } | 990 } |
962 | 991 |
963 /* Set lattice value to bottom, if it already isn't the case. */ | 992 /* Set lattice value to bottom, if it already isn't the case. */ |
964 | 993 |
1062 widest_int adjusted_value, adjusted_mask; | 1091 widest_int adjusted_value, adjusted_mask; |
1063 | 1092 |
1064 if (TREE_CODE_CLASS (code) == tcc_binary) | 1093 if (TREE_CODE_CLASS (code) == tcc_binary) |
1065 { | 1094 { |
1066 tree type = TREE_TYPE (operand); | 1095 tree type = TREE_TYPE (operand); |
1067 gcc_assert (INTEGRAL_TYPE_P (type)); | |
1068 widest_int o_value, o_mask; | 1096 widest_int o_value, o_mask; |
1069 get_value_and_mask (operand, &o_value, &o_mask); | 1097 get_value_and_mask (operand, &o_value, &o_mask); |
1070 | 1098 |
1071 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask, | 1099 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask, |
1072 sgn, precision, other.get_value (), other.get_mask (), | 1100 sgn, precision, other.get_value (), other.get_mask (), |
1101 | 1129 |
1102 /* Mark bot aggregate and scalar lattices as containing an unknown variable, | 1130 /* Mark bot aggregate and scalar lattices as containing an unknown variable, |
1103 return true is any of them has not been marked as such so far. */ | 1131 return true is any of them has not been marked as such so far. */ |
1104 | 1132 |
1105 static inline bool | 1133 static inline bool |
1106 set_all_contains_variable (struct ipcp_param_lattices *plats) | 1134 set_all_contains_variable (class ipcp_param_lattices *plats) |
1107 { | 1135 { |
1108 bool ret; | 1136 bool ret; |
1109 ret = plats->itself.set_contains_variable (); | 1137 ret = plats->itself.set_contains_variable (); |
1110 ret |= plats->ctxlat.set_contains_variable (); | 1138 ret |= plats->ctxlat.set_contains_variable (); |
1111 ret |= set_agg_lats_contain_variable (plats); | 1139 ret |= set_agg_lats_contain_variable (plats); |
1121 count_callers (cgraph_node *node, void *data) | 1149 count_callers (cgraph_node *node, void *data) |
1122 { | 1150 { |
1123 int *caller_count = (int *) data; | 1151 int *caller_count = (int *) data; |
1124 | 1152 |
1125 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller) | 1153 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller) |
1126 /* Local thunks can be handled transparently, but if the thunk can not | 1154 /* Local thunks can be handled transparently, but if the thunk cannot |
1127 be optimized out, count it as a real use. */ | 1155 be optimized out, count it as a real use. */ |
1128 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local) | 1156 if (!cs->caller->thunk.thunk_p || !cs->caller->local) |
1129 ++*caller_count; | 1157 ++*caller_count; |
1130 return false; | 1158 return false; |
1131 } | 1159 } |
1132 | 1160 |
1133 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on | 1161 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on |
1136 static bool | 1164 static bool |
1137 set_single_call_flag (cgraph_node *node, void *) | 1165 set_single_call_flag (cgraph_node *node, void *) |
1138 { | 1166 { |
1139 cgraph_edge *cs = node->callers; | 1167 cgraph_edge *cs = node->callers; |
1140 /* Local thunks can be handled transparently, skip them. */ | 1168 /* Local thunks can be handled transparently, skip them. */ |
1141 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local) | 1169 while (cs && cs->caller->thunk.thunk_p && cs->caller->local) |
1142 cs = cs->next_caller; | 1170 cs = cs->next_caller; |
1143 if (cs) | 1171 if (cs && IPA_NODE_REF (cs->caller)) |
1144 { | 1172 { |
1145 IPA_NODE_REF (cs->caller)->node_calling_single_call = true; | 1173 IPA_NODE_REF (cs->caller)->node_calling_single_call = true; |
1146 return true; | 1174 return true; |
1147 } | 1175 } |
1148 return false; | 1176 return false; |
1151 /* Initialize ipcp_lattices. */ | 1179 /* Initialize ipcp_lattices. */ |
1152 | 1180 |
1153 static void | 1181 static void |
1154 initialize_node_lattices (struct cgraph_node *node) | 1182 initialize_node_lattices (struct cgraph_node *node) |
1155 { | 1183 { |
1156 struct ipa_node_params *info = IPA_NODE_REF (node); | 1184 class ipa_node_params *info = IPA_NODE_REF (node); |
1157 struct cgraph_edge *ie; | 1185 struct cgraph_edge *ie; |
1158 bool disable = false, variable = false; | 1186 bool disable = false, variable = false; |
1159 int i; | 1187 int i; |
1160 | 1188 |
1161 gcc_checking_assert (node->has_gimple_body_p ()); | 1189 gcc_checking_assert (node->has_gimple_body_p ()); |
1162 if (node->local.local) | 1190 |
1191 if (!ipa_get_param_count (info)) | |
1192 disable = true; | |
1193 else if (node->local) | |
1163 { | 1194 { |
1164 int caller_count = 0; | 1195 int caller_count = 0; |
1165 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, | 1196 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, |
1166 true); | 1197 true); |
1167 gcc_checking_assert (caller_count > 0); | 1198 gcc_checking_assert (caller_count > 0); |
1179 variable = true; | 1210 variable = true; |
1180 else | 1211 else |
1181 disable = true; | 1212 disable = true; |
1182 } | 1213 } |
1183 | 1214 |
1184 for (i = 0; i < ipa_get_param_count (info); i++) | 1215 if (dump_file && (dump_flags & TDF_DETAILS) |
1185 { | 1216 && !node->alias && !node->thunk.thunk_p) |
1186 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 1217 { |
1187 plats->m_value_range.init (); | 1218 fprintf (dump_file, "Initializing lattices of %s\n", |
1188 } | 1219 node->dump_name ()); |
1189 | 1220 if (disable || variable) |
1190 if (disable || variable) | 1221 fprintf (dump_file, " Marking all lattices as %s\n", |
1191 { | 1222 disable ? "BOTTOM" : "VARIABLE"); |
1192 for (i = 0; i < ipa_get_param_count (info); i++) | 1223 } |
1193 { | 1224 |
1194 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 1225 auto_vec<bool, 16> surviving_params; |
1195 if (disable) | 1226 bool pre_modified = false; |
1196 { | 1227 if (!disable && node->clone.param_adjustments) |
1197 plats->itself.set_to_bottom (); | 1228 { |
1198 plats->ctxlat.set_to_bottom (); | 1229 /* At the moment all IPA optimizations should use the number of |
1199 set_agg_lats_to_bottom (plats); | 1230 parameters of the prevailing decl as the m_always_copy_start. |
1200 plats->bits_lattice.set_to_bottom (); | 1231 Handling any other value would complicate the code below, so for the |
1201 plats->m_value_range.set_to_bottom (); | 1232 time bing let's only assert it is so. */ |
1202 } | 1233 gcc_assert ((node->clone.param_adjustments->m_always_copy_start |
1203 else | 1234 == ipa_get_param_count (info)) |
1204 set_all_contains_variable (plats); | 1235 || node->clone.param_adjustments->m_always_copy_start < 0); |
1205 } | 1236 |
1237 pre_modified = true; | |
1238 node->clone.param_adjustments->get_surviving_params (&surviving_params); | |
1239 | |
1206 if (dump_file && (dump_flags & TDF_DETAILS) | 1240 if (dump_file && (dump_flags & TDF_DETAILS) |
1207 && !node->alias && !node->thunk.thunk_p) | 1241 && !node->alias && !node->thunk.thunk_p) |
1208 fprintf (dump_file, "Marking all lattices of %s as %s\n", | 1242 { |
1209 node->dump_name (), disable ? "BOTTOM" : "VARIABLE"); | 1243 bool first = true; |
1244 for (int j = 0; j < ipa_get_param_count (info); j++) | |
1245 { | |
1246 if (j < (int) surviving_params.length () | |
1247 && surviving_params[j]) | |
1248 continue; | |
1249 if (first) | |
1250 { | |
1251 fprintf (dump_file, | |
1252 " The following parameters are dead on arrival:"); | |
1253 first = false; | |
1254 } | |
1255 fprintf (dump_file, " %u", j); | |
1256 } | |
1257 if (!first) | |
1258 fprintf (dump_file, "\n"); | |
1259 } | |
1260 } | |
1261 | |
1262 for (i = 0; i < ipa_get_param_count (info); i++) | |
1263 { | |
1264 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
1265 if (disable | |
1266 || (pre_modified && (surviving_params.length () <= (unsigned) i | |
1267 || !surviving_params[i]))) | |
1268 { | |
1269 plats->itself.set_to_bottom (); | |
1270 plats->ctxlat.set_to_bottom (); | |
1271 set_agg_lats_to_bottom (plats); | |
1272 plats->bits_lattice.set_to_bottom (); | |
1273 plats->m_value_range.set_to_bottom (); | |
1274 } | |
1275 else | |
1276 { | |
1277 plats->m_value_range.init (); | |
1278 if (variable) | |
1279 set_all_contains_variable (plats); | |
1280 } | |
1210 } | 1281 } |
1211 | 1282 |
1212 for (ie = node->indirect_calls; ie; ie = ie->next_callee) | 1283 for (ie = node->indirect_calls; ie; ie = ie->next_callee) |
1213 if (ie->indirect_info->polymorphic | 1284 if (ie->indirect_info->polymorphic |
1214 && ie->indirect_info->param_index >= 0) | 1285 && ie->indirect_info->param_index >= 0) |
1217 ipa_get_parm_lattices (info, | 1288 ipa_get_parm_lattices (info, |
1218 ie->indirect_info->param_index)->virt_call = 1; | 1289 ie->indirect_info->param_index)->virt_call = 1; |
1219 } | 1290 } |
1220 } | 1291 } |
1221 | 1292 |
1222 /* Return the result of a (possibly arithmetic) pass through jump function | 1293 /* Return the result of a (possibly arithmetic) operation on the constant |
1223 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter | 1294 value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is |
1224 to which the result is passed. Return NULL_TREE if that cannot be | 1295 the type of the parameter to which the result is passed. Return |
1225 determined or be considered an interprocedural invariant. */ | 1296 NULL_TREE if that cannot be determined or be considered an |
1297 interprocedural invariant. */ | |
1226 | 1298 |
1227 static tree | 1299 static tree |
1228 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, | 1300 ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand, |
1229 tree res_type) | 1301 tree res_type) |
1230 { | 1302 { |
1231 tree res; | 1303 tree res; |
1232 | 1304 |
1233 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | 1305 if (opcode == NOP_EXPR) |
1234 return input; | 1306 return input; |
1235 if (!is_gimple_ip_invariant (input)) | 1307 if (!is_gimple_ip_invariant (input)) |
1236 return NULL_TREE; | 1308 return NULL_TREE; |
1237 | 1309 |
1238 tree_code opcode = ipa_get_jf_pass_through_operation (jfunc); | |
1239 if (!res_type) | 1310 if (!res_type) |
1240 { | 1311 { |
1241 if (TREE_CODE_CLASS (opcode) == tcc_comparison) | 1312 if (TREE_CODE_CLASS (opcode) == tcc_comparison) |
1242 res_type = boolean_type_node; | 1313 res_type = boolean_type_node; |
1243 else if (expr_type_first_operand_type_p (opcode)) | 1314 else if (expr_type_first_operand_type_p (opcode)) |
1247 } | 1318 } |
1248 | 1319 |
1249 if (TREE_CODE_CLASS (opcode) == tcc_unary) | 1320 if (TREE_CODE_CLASS (opcode) == tcc_unary) |
1250 res = fold_unary (opcode, res_type, input); | 1321 res = fold_unary (opcode, res_type, input); |
1251 else | 1322 else |
1252 res = fold_binary (opcode, res_type, input, | 1323 res = fold_binary (opcode, res_type, input, operand); |
1253 ipa_get_jf_pass_through_operand (jfunc)); | |
1254 | 1324 |
1255 if (res && !is_gimple_ip_invariant (res)) | 1325 if (res && !is_gimple_ip_invariant (res)) |
1256 return NULL_TREE; | 1326 return NULL_TREE; |
1257 | 1327 |
1258 return res; | 1328 return res; |
1329 } | |
1330 | |
1331 /* Return the result of a (possibly arithmetic) pass through jump function | |
1332 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter | |
1333 to which the result is passed. Return NULL_TREE if that cannot be | |
1334 determined or be considered an interprocedural invariant. */ | |
1335 | |
1336 static tree | |
1337 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, | |
1338 tree res_type) | |
1339 { | |
1340 return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc), | |
1341 input, | |
1342 ipa_get_jf_pass_through_operand (jfunc), | |
1343 res_type); | |
1259 } | 1344 } |
1260 | 1345 |
1261 /* Return the result of an ancestor jump function JFUNC on the constant value | 1346 /* Return the result of an ancestor jump function JFUNC on the constant value |
1262 INPUT. Return NULL_TREE if that cannot be determined. */ | 1347 INPUT. Return NULL_TREE if that cannot be determined. */ |
1263 | 1348 |
1282 the one it is inlined to, so that pass-through jump functions can be | 1367 the one it is inlined to, so that pass-through jump functions can be |
1283 evaluated. PARM_TYPE is the type of the parameter to which the result is | 1368 evaluated. PARM_TYPE is the type of the parameter to which the result is |
1284 passed. */ | 1369 passed. */ |
1285 | 1370 |
1286 tree | 1371 tree |
1287 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc, | 1372 ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc, |
1288 tree parm_type) | 1373 tree parm_type) |
1289 { | 1374 { |
1290 if (jfunc->type == IPA_JF_CONST) | 1375 if (jfunc->type == IPA_JF_CONST) |
1291 return ipa_get_jf_constant (jfunc); | 1376 return ipa_get_jf_constant (jfunc); |
1292 else if (jfunc->type == IPA_JF_PASS_THROUGH | 1377 else if (jfunc->type == IPA_JF_PASS_THROUGH |
1325 } | 1410 } |
1326 else | 1411 else |
1327 return NULL_TREE; | 1412 return NULL_TREE; |
1328 } | 1413 } |
1329 | 1414 |
1330 /* Determie whether JFUNC evaluates to single known polymorphic context, given | 1415 /* Determine whether JFUNC evaluates to single known polymorphic context, given |
1331 that INFO describes the caller node or the one it is inlined to, CS is the | 1416 that INFO describes the caller node or the one it is inlined to, CS is the |
1332 call graph edge corresponding to JFUNC and CSIDX index of the described | 1417 call graph edge corresponding to JFUNC and CSIDX index of the described |
1333 parameter. */ | 1418 parameter. */ |
1334 | 1419 |
1335 ipa_polymorphic_call_context | 1420 ipa_polymorphic_call_context |
1389 } | 1474 } |
1390 | 1475 |
1391 return ctx; | 1476 return ctx; |
1392 } | 1477 } |
1393 | 1478 |
1479 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to | |
1480 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if | |
1481 the result is a range or an anti-range. */ | |
1482 | |
1483 static bool | |
1484 ipa_vr_operation_and_type_effects (value_range *dst_vr, | |
1485 value_range *src_vr, | |
1486 enum tree_code operation, | |
1487 tree dst_type, tree src_type) | |
1488 { | |
1489 range_fold_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); | |
1490 if (dst_vr->varying_p () || dst_vr->undefined_p ()) | |
1491 return false; | |
1492 return true; | |
1493 } | |
1494 | |
1495 /* Determine value_range of JFUNC given that INFO describes the caller node or | |
1496 the one it is inlined to, CS is the call graph edge corresponding to JFUNC | |
1497 and PARM_TYPE of the parameter. */ | |
1498 | |
1499 value_range | |
1500 ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs, | |
1501 ipa_jump_func *jfunc, tree parm_type) | |
1502 { | |
1503 value_range vr; | |
1504 return vr; | |
1505 if (jfunc->m_vr) | |
1506 ipa_vr_operation_and_type_effects (&vr, | |
1507 jfunc->m_vr, | |
1508 NOP_EXPR, parm_type, | |
1509 jfunc->m_vr->type ()); | |
1510 if (vr.singleton_p ()) | |
1511 return vr; | |
1512 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1513 { | |
1514 int idx; | |
1515 ipcp_transformation *sum | |
1516 = ipcp_get_transformation_summary (cs->caller->inlined_to | |
1517 ? cs->caller->inlined_to | |
1518 : cs->caller); | |
1519 if (!sum || !sum->m_vr) | |
1520 return vr; | |
1521 | |
1522 idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
1523 | |
1524 if (!(*sum->m_vr)[idx].known) | |
1525 return vr; | |
1526 tree vr_type = ipa_get_type (info, idx); | |
1527 value_range srcvr (wide_int_to_tree (vr_type, (*sum->m_vr)[idx].min), | |
1528 wide_int_to_tree (vr_type, (*sum->m_vr)[idx].max), | |
1529 (*sum->m_vr)[idx].type); | |
1530 | |
1531 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); | |
1532 | |
1533 if (TREE_CODE_CLASS (operation) == tcc_unary) | |
1534 { | |
1535 value_range res; | |
1536 | |
1537 if (ipa_vr_operation_and_type_effects (&res, | |
1538 &srcvr, | |
1539 operation, parm_type, | |
1540 vr_type)) | |
1541 vr.intersect (res); | |
1542 } | |
1543 else | |
1544 { | |
1545 value_range op_res, res; | |
1546 tree op = ipa_get_jf_pass_through_operand (jfunc); | |
1547 value_range op_vr (op, op); | |
1548 | |
1549 range_fold_binary_expr (&op_res, operation, vr_type, &srcvr, &op_vr); | |
1550 if (ipa_vr_operation_and_type_effects (&res, | |
1551 &op_res, | |
1552 NOP_EXPR, parm_type, | |
1553 vr_type)) | |
1554 vr.intersect (res); | |
1555 } | |
1556 } | |
1557 return vr; | |
1558 } | |
1559 | |
1560 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a | |
1561 parameter with the given INDEX. */ | |
1562 | |
1563 static tree | |
1564 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, | |
1565 int index) | |
1566 { | |
1567 struct ipa_agg_replacement_value *aggval; | |
1568 | |
1569 aggval = ipa_get_agg_replacements_for_node (node); | |
1570 while (aggval) | |
1571 { | |
1572 if (aggval->offset == offset | |
1573 && aggval->index == index) | |
1574 return aggval->value; | |
1575 aggval = aggval->next; | |
1576 } | |
1577 return NULL_TREE; | |
1578 } | |
1579 | |
1580 /* Determine whether ITEM, jump function for an aggregate part, evaluates to a | |
1581 single known constant value and if so, return it. Otherwise return NULL. | |
1582 NODE and INFO describes the caller node or the one it is inlined to, and | |
1583 its related info. */ | |
1584 | |
1585 static tree | |
1586 ipa_agg_value_from_node (class ipa_node_params *info, | |
1587 struct cgraph_node *node, | |
1588 struct ipa_agg_jf_item *item) | |
1589 { | |
1590 tree value = NULL_TREE; | |
1591 int src_idx; | |
1592 | |
1593 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN) | |
1594 return NULL_TREE; | |
1595 | |
1596 if (item->jftype == IPA_JF_CONST) | |
1597 return item->value.constant; | |
1598 | |
1599 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH | |
1600 || item->jftype == IPA_JF_LOAD_AGG); | |
1601 | |
1602 src_idx = item->value.pass_through.formal_id; | |
1603 | |
1604 if (info->ipcp_orig_node) | |
1605 { | |
1606 if (item->jftype == IPA_JF_PASS_THROUGH) | |
1607 value = info->known_csts[src_idx]; | |
1608 else | |
1609 value = get_clone_agg_value (node, item->value.load_agg.offset, | |
1610 src_idx); | |
1611 } | |
1612 else if (info->lattices) | |
1613 { | |
1614 class ipcp_param_lattices *src_plats | |
1615 = ipa_get_parm_lattices (info, src_idx); | |
1616 | |
1617 if (item->jftype == IPA_JF_PASS_THROUGH) | |
1618 { | |
1619 struct ipcp_lattice<tree> *lat = &src_plats->itself; | |
1620 | |
1621 if (!lat->is_single_const ()) | |
1622 return NULL_TREE; | |
1623 | |
1624 value = lat->values->value; | |
1625 } | |
1626 else if (src_plats->aggs | |
1627 && !src_plats->aggs_bottom | |
1628 && !src_plats->aggs_contain_variable | |
1629 && src_plats->aggs_by_ref == item->value.load_agg.by_ref) | |
1630 { | |
1631 struct ipcp_agg_lattice *aglat; | |
1632 | |
1633 for (aglat = src_plats->aggs; aglat; aglat = aglat->next) | |
1634 { | |
1635 if (aglat->offset > item->value.load_agg.offset) | |
1636 break; | |
1637 | |
1638 if (aglat->offset == item->value.load_agg.offset) | |
1639 { | |
1640 if (aglat->is_single_const ()) | |
1641 value = aglat->values->value; | |
1642 break; | |
1643 } | |
1644 } | |
1645 } | |
1646 } | |
1647 | |
1648 if (!value) | |
1649 return NULL_TREE; | |
1650 | |
1651 if (item->jftype == IPA_JF_LOAD_AGG) | |
1652 { | |
1653 tree load_type = item->value.load_agg.type; | |
1654 tree value_type = TREE_TYPE (value); | |
1655 | |
1656 /* Ensure value type is compatible with load type. */ | |
1657 if (!useless_type_conversion_p (load_type, value_type)) | |
1658 return NULL_TREE; | |
1659 } | |
1660 | |
1661 return ipa_get_jf_arith_result (item->value.pass_through.operation, | |
1662 value, | |
1663 item->value.pass_through.operand, | |
1664 item->type); | |
1665 } | |
1666 | |
1667 /* Determine whether AGG_JFUNC evaluates to a set of known constant value for | |
1668 an aggregate and if so, return it. Otherwise return an empty set. NODE | |
1669 and INFO describes the caller node or the one it is inlined to, and its | |
1670 related info. */ | |
1671 | |
1672 struct ipa_agg_value_set | |
1673 ipa_agg_value_set_from_jfunc (class ipa_node_params *info, cgraph_node *node, | |
1674 struct ipa_agg_jump_function *agg_jfunc) | |
1675 { | |
1676 struct ipa_agg_value_set agg; | |
1677 struct ipa_agg_jf_item *item; | |
1678 int i; | |
1679 | |
1680 agg.items = vNULL; | |
1681 agg.by_ref = agg_jfunc->by_ref; | |
1682 | |
1683 FOR_EACH_VEC_SAFE_ELT (agg_jfunc->items, i, item) | |
1684 { | |
1685 tree value = ipa_agg_value_from_node (info, node, item); | |
1686 | |
1687 if (value) | |
1688 { | |
1689 struct ipa_agg_value value_item; | |
1690 | |
1691 value_item.offset = item->offset; | |
1692 value_item.value = value; | |
1693 | |
1694 agg.items.safe_push (value_item); | |
1695 } | |
1696 } | |
1697 return agg; | |
1698 } | |
1699 | |
1394 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not | 1700 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not |
1395 bottom, not containing a variable component and without any known value at | 1701 bottom, not containing a variable component and without any known value at |
1396 the same time. */ | 1702 the same time. */ |
1397 | 1703 |
1398 DEBUG_FUNCTION void | 1704 DEBUG_FUNCTION void |
1400 { | 1706 { |
1401 struct cgraph_node *node; | 1707 struct cgraph_node *node; |
1402 | 1708 |
1403 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | 1709 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) |
1404 { | 1710 { |
1405 struct ipa_node_params *info = IPA_NODE_REF (node); | 1711 class ipa_node_params *info = IPA_NODE_REF (node); |
1712 if (!opt_for_fn (node->decl, flag_ipa_cp) | |
1713 || !opt_for_fn (node->decl, optimize)) | |
1714 continue; | |
1406 int i, count = ipa_get_param_count (info); | 1715 int i, count = ipa_get_param_count (info); |
1407 | 1716 |
1408 for (i = 0; i < count; i++) | 1717 for (i = 0; i < count; i++) |
1409 { | 1718 { |
1410 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); | 1719 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); |
1509 } | 1818 } |
1510 | 1819 |
1511 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS, | 1820 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS, |
1512 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same | 1821 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same |
1513 meaning. OFFSET -1 means the source is scalar and not a part of an | 1822 meaning. OFFSET -1 means the source is scalar and not a part of an |
1514 aggregate. */ | 1823 aggregate. If non-NULL, VAL_P records address of existing or newly added |
1824 ipcp_value. UNLIMITED means whether value count should not exceed the limit | |
1825 given by PARAM_IPA_CP_VALUE_LIST_SIZE. */ | |
1515 | 1826 |
1516 template <typename valtype> | 1827 template <typename valtype> |
1517 bool | 1828 bool |
1518 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs, | 1829 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs, |
1519 ipcp_value<valtype> *src_val, | 1830 ipcp_value<valtype> *src_val, |
1520 int src_idx, HOST_WIDE_INT offset) | 1831 int src_idx, HOST_WIDE_INT offset, |
1521 { | 1832 ipcp_value<valtype> **val_p, |
1522 ipcp_value<valtype> *val; | 1833 bool unlimited) |
1834 { | |
1835 ipcp_value<valtype> *val, *last_val = NULL; | |
1836 | |
1837 if (val_p) | |
1838 *val_p = NULL; | |
1523 | 1839 |
1524 if (bottom) | 1840 if (bottom) |
1525 return false; | 1841 return false; |
1526 | 1842 |
1527 for (val = values; val; val = val->next) | 1843 for (val = values; val; last_val = val, val = val->next) |
1528 if (values_equal_for_ipcp_p (val->value, newval)) | 1844 if (values_equal_for_ipcp_p (val->value, newval)) |
1529 { | 1845 { |
1846 if (val_p) | |
1847 *val_p = val; | |
1848 | |
1530 if (ipa_edge_within_scc (cs)) | 1849 if (ipa_edge_within_scc (cs)) |
1531 { | 1850 { |
1532 ipcp_value_source<valtype> *s; | 1851 ipcp_value_source<valtype> *s; |
1533 for (s = val->sources; s; s = s->next) | 1852 for (s = val->sources; s; s = s->next) |
1534 if (s->cs == cs) | 1853 if (s->cs == cs && s->val == src_val) |
1535 break; | 1854 break; |
1536 if (s) | 1855 if (s) |
1537 return false; | 1856 return false; |
1538 } | 1857 } |
1539 | 1858 |
1540 val->add_source (cs, src_val, src_idx, offset); | 1859 val->add_source (cs, src_val, src_idx, offset); |
1541 return false; | 1860 return false; |
1542 } | 1861 } |
1543 | 1862 |
1544 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE)) | 1863 if (!unlimited && values_count == opt_for_fn (cs->caller->decl, |
1864 param_ipa_cp_value_list_size)) | |
1545 { | 1865 { |
1546 /* We can only free sources, not the values themselves, because sources | 1866 /* We can only free sources, not the values themselves, because sources |
1547 of other values in this SCC might point to them. */ | 1867 of other values in this SCC might point to them. */ |
1548 for (val = values; val; val = val->next) | 1868 for (val = values; val; val = val->next) |
1549 { | 1869 { |
1552 ipcp_value_source<valtype> *src = val->sources; | 1872 ipcp_value_source<valtype> *src = val->sources; |
1553 val->sources = src->next; | 1873 val->sources = src->next; |
1554 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src); | 1874 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src); |
1555 } | 1875 } |
1556 } | 1876 } |
1557 | |
1558 values = NULL; | 1877 values = NULL; |
1559 return set_to_bottom (); | 1878 return set_to_bottom (); |
1560 } | 1879 } |
1561 | 1880 |
1562 values_count++; | 1881 values_count++; |
1563 val = allocate_and_init_ipcp_value (newval); | 1882 val = allocate_and_init_ipcp_value (newval); |
1564 val->add_source (cs, src_val, src_idx, offset); | 1883 val->add_source (cs, src_val, src_idx, offset); |
1565 val->next = values; | 1884 val->next = NULL; |
1566 values = val; | 1885 |
1886 /* Add the new value to end of value list, which can reduce iterations | |
1887 of propagation stage for recursive function. */ | |
1888 if (last_val) | |
1889 last_val->next = val; | |
1890 else | |
1891 values = val; | |
1892 | |
1893 if (val_p) | |
1894 *val_p = val; | |
1895 | |
1567 return true; | 1896 return true; |
1897 } | |
1898 | |
1899 /* Return true, if a ipcp_value VAL is orginated from parameter value of | |
1900 self-feeding recursive function by applying non-passthrough arithmetic | |
1901 transformation. */ | |
1902 | |
1903 static bool | |
1904 self_recursively_generated_p (ipcp_value<tree> *val) | |
1905 { | |
1906 class ipa_node_params *info = NULL; | |
1907 | |
1908 for (ipcp_value_source<tree> *src = val->sources; src; src = src->next) | |
1909 { | |
1910 cgraph_edge *cs = src->cs; | |
1911 | |
1912 if (!src->val || cs->caller != cs->callee->function_symbol () | |
1913 || src->val == val) | |
1914 return false; | |
1915 | |
1916 if (!info) | |
1917 info = IPA_NODE_REF (cs->caller); | |
1918 | |
1919 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, | |
1920 src->index); | |
1921 ipcp_lattice<tree> *src_lat; | |
1922 ipcp_value<tree> *src_val; | |
1923 | |
1924 if (src->offset == -1) | |
1925 src_lat = &plats->itself; | |
1926 else | |
1927 { | |
1928 struct ipcp_agg_lattice *src_aglat; | |
1929 | |
1930 for (src_aglat = plats->aggs; src_aglat; src_aglat = src_aglat->next) | |
1931 if (src_aglat->offset == src->offset) | |
1932 break; | |
1933 | |
1934 if (!src_aglat) | |
1935 return false; | |
1936 | |
1937 src_lat = src_aglat; | |
1938 } | |
1939 | |
1940 for (src_val = src_lat->values; src_val; src_val = src_val->next) | |
1941 if (src_val == val) | |
1942 break; | |
1943 | |
1944 if (!src_val) | |
1945 return false; | |
1946 } | |
1947 | |
1948 return true; | |
1949 } | |
1950 | |
1951 /* A helper function that returns result of operation specified by OPCODE on | |
1952 the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the | |
1953 value of SRC_VAL. If the operation is binary, OPND2 is a constant value | |
1954 acting as its second operand. If non-NULL, RES_TYPE is expected type of | |
1955 the result. */ | |
1956 | |
1957 static tree | |
1958 get_val_across_arith_op (enum tree_code opcode, | |
1959 tree opnd1_type, | |
1960 tree opnd2, | |
1961 ipcp_value<tree> *src_val, | |
1962 tree res_type) | |
1963 { | |
1964 tree opnd1 = src_val->value; | |
1965 | |
1966 /* Skip source values that is incompatible with specified type. */ | |
1967 if (opnd1_type | |
1968 && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1))) | |
1969 return NULL_TREE; | |
1970 | |
1971 return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type); | |
1972 } | |
1973 | |
1974 /* Propagate values through an arithmetic transformation described by a jump | |
1975 function associated with edge CS, taking values from SRC_LAT and putting | |
1976 them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT. | |
1977 OPND2 is a constant value if transformation is a binary operation. | |
1978 SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of | |
1979 a part of the aggregate. SRC_IDX is the index of the source parameter. | |
1980 RES_TYPE is the value type of result being propagated into. Return true if | |
1981 DEST_LAT changed. */ | |
1982 | |
1983 static bool | |
1984 propagate_vals_across_arith_jfunc (cgraph_edge *cs, | |
1985 enum tree_code opcode, | |
1986 tree opnd1_type, | |
1987 tree opnd2, | |
1988 ipcp_lattice<tree> *src_lat, | |
1989 ipcp_lattice<tree> *dest_lat, | |
1990 HOST_WIDE_INT src_offset, | |
1991 int src_idx, | |
1992 tree res_type) | |
1993 { | |
1994 ipcp_value<tree> *src_val; | |
1995 bool ret = false; | |
1996 | |
1997 /* Due to circular dependencies, propagating within an SCC through arithmetic | |
1998 transformation would create infinite number of values. But for | |
1999 self-feeding recursive function, we could allow propagation in a limited | |
2000 count, and this can enable a simple kind of recursive function versioning. | |
2001 For other scenario, we would just make lattices bottom. */ | |
2002 if (opcode != NOP_EXPR && ipa_edge_within_scc (cs)) | |
2003 { | |
2004 int i; | |
2005 | |
2006 int max_recursive_depth = opt_for_fn(cs->caller->decl, | |
2007 param_ipa_cp_max_recursive_depth); | |
2008 if (src_lat != dest_lat || max_recursive_depth < 1) | |
2009 return dest_lat->set_contains_variable (); | |
2010 | |
2011 /* No benefit if recursive execution is in low probability. */ | |
2012 if (cs->sreal_frequency () * 100 | |
2013 <= ((sreal) 1) * opt_for_fn (cs->caller->decl, | |
2014 param_ipa_cp_min_recursive_probability)) | |
2015 return dest_lat->set_contains_variable (); | |
2016 | |
2017 auto_vec<ipcp_value<tree> *, 8> val_seeds; | |
2018 | |
2019 for (src_val = src_lat->values; src_val; src_val = src_val->next) | |
2020 { | |
2021 /* Now we do not use self-recursively generated value as propagation | |
2022 source, this is absolutely conservative, but could avoid explosion | |
2023 of lattice's value space, especially when one recursive function | |
2024 calls another recursive. */ | |
2025 if (self_recursively_generated_p (src_val)) | |
2026 { | |
2027 ipcp_value_source<tree> *s; | |
2028 | |
2029 /* If the lattice has already been propagated for the call site, | |
2030 no need to do that again. */ | |
2031 for (s = src_val->sources; s; s = s->next) | |
2032 if (s->cs == cs) | |
2033 return dest_lat->set_contains_variable (); | |
2034 } | |
2035 else | |
2036 val_seeds.safe_push (src_val); | |
2037 } | |
2038 | |
2039 gcc_assert ((int) val_seeds.length () <= param_ipa_cp_value_list_size); | |
2040 | |
2041 /* Recursively generate lattice values with a limited count. */ | |
2042 FOR_EACH_VEC_ELT (val_seeds, i, src_val) | |
2043 { | |
2044 for (int j = 1; j < max_recursive_depth; j++) | |
2045 { | |
2046 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2, | |
2047 src_val, res_type); | |
2048 if (!cstval) | |
2049 break; | |
2050 | |
2051 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx, | |
2052 src_offset, &src_val, true); | |
2053 gcc_checking_assert (src_val); | |
2054 } | |
2055 } | |
2056 ret |= dest_lat->set_contains_variable (); | |
2057 } | |
2058 else | |
2059 for (src_val = src_lat->values; src_val; src_val = src_val->next) | |
2060 { | |
2061 /* Now we do not use self-recursively generated value as propagation | |
2062 source, otherwise it is easy to make value space of normal lattice | |
2063 overflow. */ | |
2064 if (self_recursively_generated_p (src_val)) | |
2065 { | |
2066 ret |= dest_lat->set_contains_variable (); | |
2067 continue; | |
2068 } | |
2069 | |
2070 tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2, | |
2071 src_val, res_type); | |
2072 if (cstval) | |
2073 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx, | |
2074 src_offset); | |
2075 else | |
2076 ret |= dest_lat->set_contains_variable (); | |
2077 } | |
2078 | |
2079 return ret; | |
1568 } | 2080 } |
1569 | 2081 |
1570 /* Propagate values through a pass-through jump function JFUNC associated with | 2082 /* Propagate values through a pass-through jump function JFUNC associated with |
1571 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX | 2083 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX |
1572 is the index of the source parameter. PARM_TYPE is the type of the | 2084 is the index of the source parameter. PARM_TYPE is the type of the |
1576 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, | 2088 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, |
1577 ipcp_lattice<tree> *src_lat, | 2089 ipcp_lattice<tree> *src_lat, |
1578 ipcp_lattice<tree> *dest_lat, int src_idx, | 2090 ipcp_lattice<tree> *dest_lat, int src_idx, |
1579 tree parm_type) | 2091 tree parm_type) |
1580 { | 2092 { |
1581 ipcp_value<tree> *src_val; | 2093 return propagate_vals_across_arith_jfunc (cs, |
1582 bool ret = false; | 2094 ipa_get_jf_pass_through_operation (jfunc), |
1583 | 2095 NULL_TREE, |
1584 /* Do not create new values when propagating within an SCC because if there | 2096 ipa_get_jf_pass_through_operand (jfunc), |
1585 are arithmetic functions with circular dependencies, there is infinite | 2097 src_lat, dest_lat, -1, src_idx, parm_type); |
1586 number of them and we would just make lattices bottom. If this condition | |
1587 is ever relaxed we have to detect self-feeding recursive calls in | |
1588 cgraph_edge_brings_value_p in a smarter way. */ | |
1589 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) | |
1590 && ipa_edge_within_scc (cs)) | |
1591 ret = dest_lat->set_contains_variable (); | |
1592 else | |
1593 for (src_val = src_lat->values; src_val; src_val = src_val->next) | |
1594 { | |
1595 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value, | |
1596 parm_type); | |
1597 | |
1598 if (cstval) | |
1599 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); | |
1600 else | |
1601 ret |= dest_lat->set_contains_variable (); | |
1602 } | |
1603 | |
1604 return ret; | |
1605 } | 2098 } |
1606 | 2099 |
1607 /* Propagate values through an ancestor jump function JFUNC associated with | 2100 /* Propagate values through an ancestor jump function JFUNC associated with |
1608 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX | 2101 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX |
1609 is the index of the source parameter. */ | 2102 is the index of the source parameter. */ |
1652 return dest_lat->add_value (val, cs, NULL, 0); | 2145 return dest_lat->add_value (val, cs, NULL, 0); |
1653 } | 2146 } |
1654 else if (jfunc->type == IPA_JF_PASS_THROUGH | 2147 else if (jfunc->type == IPA_JF_PASS_THROUGH |
1655 || jfunc->type == IPA_JF_ANCESTOR) | 2148 || jfunc->type == IPA_JF_ANCESTOR) |
1656 { | 2149 { |
1657 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 2150 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
1658 ipcp_lattice<tree> *src_lat; | 2151 ipcp_lattice<tree> *src_lat; |
1659 int src_idx; | 2152 int src_idx; |
1660 bool ret; | 2153 bool ret; |
1661 | 2154 |
1662 if (jfunc->type == IPA_JF_PASS_THROUGH) | 2155 if (jfunc->type == IPA_JF_PASS_THROUGH) |
1714 edge_ctx = *edge_ctx_ptr; | 2207 edge_ctx = *edge_ctx_ptr; |
1715 | 2208 |
1716 if (jfunc->type == IPA_JF_PASS_THROUGH | 2209 if (jfunc->type == IPA_JF_PASS_THROUGH |
1717 || jfunc->type == IPA_JF_ANCESTOR) | 2210 || jfunc->type == IPA_JF_ANCESTOR) |
1718 { | 2211 { |
1719 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 2212 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
1720 int src_idx; | 2213 int src_idx; |
1721 ipcp_lattice<ipa_polymorphic_call_context> *src_lat; | 2214 ipcp_lattice<ipa_polymorphic_call_context> *src_lat; |
1722 | 2215 |
1723 /* TODO: Once we figure out how to propagate speculations, it will | 2216 /* TODO: Once we figure out how to propagate speculations, it will |
1724 probably be a good idea to switch to speculation if type_preserved is | 2217 probably be a good idea to switch to speculation if type_preserved is |
1762 ret |= dest_lat->set_contains_variable (); | 2255 ret |= dest_lat->set_contains_variable (); |
1763 ret |= dest_lat->add_value (cur, cs, src_val, src_idx); | 2256 ret |= dest_lat->add_value (cur, cs, src_val, src_idx); |
1764 added_sth = true; | 2257 added_sth = true; |
1765 } | 2258 } |
1766 } | 2259 } |
1767 | |
1768 } | 2260 } |
1769 | 2261 |
1770 prop_fail: | 2262 prop_fail: |
1771 if (!added_sth) | 2263 if (!added_sth) |
1772 { | 2264 { |
1790 if (dest_lattice->bottom_p ()) | 2282 if (dest_lattice->bottom_p ()) |
1791 return false; | 2283 return false; |
1792 | 2284 |
1793 enum availability availability; | 2285 enum availability availability; |
1794 cgraph_node *callee = cs->callee->function_symbol (&availability); | 2286 cgraph_node *callee = cs->callee->function_symbol (&availability); |
1795 struct ipa_node_params *callee_info = IPA_NODE_REF (callee); | 2287 class ipa_node_params *callee_info = IPA_NODE_REF (callee); |
1796 tree parm_type = ipa_get_type (callee_info, idx); | 2288 tree parm_type = ipa_get_type (callee_info, idx); |
1797 | 2289 |
1798 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the | 2290 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the |
1799 transform for these cases. Similarly, we can have bad type mismatches | 2291 transform for these cases. Similarly, we can have bad type mismatches |
1800 with LTO, avoid doing anything with those too. */ | 2292 with LTO, avoid doing anything with those too. */ |
1802 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type))) | 2294 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type))) |
1803 { | 2295 { |
1804 if (dump_file && (dump_flags & TDF_DETAILS)) | 2296 if (dump_file && (dump_flags & TDF_DETAILS)) |
1805 fprintf (dump_file, "Setting dest_lattice to bottom, because type of " | 2297 fprintf (dump_file, "Setting dest_lattice to bottom, because type of " |
1806 "param %i of %s is NULL or unsuitable for bits propagation\n", | 2298 "param %i of %s is NULL or unsuitable for bits propagation\n", |
1807 idx, cs->callee->name ()); | 2299 idx, cs->callee->dump_name ()); |
1808 | 2300 |
1809 return dest_lattice->set_to_bottom (); | 2301 return dest_lattice->set_to_bottom (); |
1810 } | 2302 } |
1811 | 2303 |
1812 unsigned precision = TYPE_PRECISION (parm_type); | 2304 unsigned precision = TYPE_PRECISION (parm_type); |
1813 signop sgn = TYPE_SIGN (parm_type); | 2305 signop sgn = TYPE_SIGN (parm_type); |
1814 | 2306 |
1815 if (jfunc->type == IPA_JF_PASS_THROUGH | 2307 if (jfunc->type == IPA_JF_PASS_THROUGH |
1816 || jfunc->type == IPA_JF_ANCESTOR) | 2308 || jfunc->type == IPA_JF_ANCESTOR) |
1817 { | 2309 { |
1818 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 2310 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
1819 tree operand = NULL_TREE; | 2311 tree operand = NULL_TREE; |
1820 enum tree_code code; | 2312 enum tree_code code; |
1821 unsigned src_idx; | 2313 unsigned src_idx; |
1822 | 2314 |
1823 if (jfunc->type == IPA_JF_PASS_THROUGH) | 2315 if (jfunc->type == IPA_JF_PASS_THROUGH) |
1833 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | 2325 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); |
1834 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT; | 2326 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT; |
1835 operand = build_int_cstu (size_type_node, offset); | 2327 operand = build_int_cstu (size_type_node, offset); |
1836 } | 2328 } |
1837 | 2329 |
1838 struct ipcp_param_lattices *src_lats | 2330 class ipcp_param_lattices *src_lats |
1839 = ipa_get_parm_lattices (caller_info, src_idx); | 2331 = ipa_get_parm_lattices (caller_info, src_idx); |
1840 | 2332 |
1841 /* Try to propagate bits if src_lattice is bottom, but jfunc is known. | 2333 /* Try to propagate bits if src_lattice is bottom, but jfunc is known. |
1842 for eg consider: | 2334 for eg consider: |
1843 int f(int x) | 2335 int f(int x) |
1864 precision); | 2356 precision); |
1865 else | 2357 else |
1866 return dest_lattice->set_to_bottom (); | 2358 return dest_lattice->set_to_bottom (); |
1867 } | 2359 } |
1868 | 2360 |
1869 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to | |
1870 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if | |
1871 the result is a range or an anti-range. */ | |
1872 | |
1873 static bool | |
1874 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, | |
1875 enum tree_code operation, | |
1876 tree dst_type, tree src_type) | |
1877 { | |
1878 *dst_vr = value_range (); | |
1879 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); | |
1880 if (dst_vr->varying_p () || dst_vr->undefined_p ()) | |
1881 return false; | |
1882 return true; | |
1883 } | |
1884 | |
1885 /* Propagate value range across jump function JFUNC that is associated with | 2361 /* Propagate value range across jump function JFUNC that is associated with |
1886 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS | 2362 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS |
1887 accordingly. */ | 2363 accordingly. */ |
1888 | 2364 |
1889 static bool | 2365 static bool |
1890 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, | 2366 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, |
1891 struct ipcp_param_lattices *dest_plats, | 2367 class ipcp_param_lattices *dest_plats, |
1892 tree param_type) | 2368 tree param_type) |
1893 { | 2369 { |
1894 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range; | 2370 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range; |
1895 | 2371 |
1896 if (dest_lat->bottom_p ()) | 2372 if (dest_lat->bottom_p ()) |
1902 return dest_lat->set_to_bottom (); | 2378 return dest_lat->set_to_bottom (); |
1903 | 2379 |
1904 if (jfunc->type == IPA_JF_PASS_THROUGH) | 2380 if (jfunc->type == IPA_JF_PASS_THROUGH) |
1905 { | 2381 { |
1906 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); | 2382 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); |
1907 | 2383 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
2384 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
2385 class ipcp_param_lattices *src_lats | |
2386 = ipa_get_parm_lattices (caller_info, src_idx); | |
2387 tree operand_type = ipa_get_type (caller_info, src_idx); | |
2388 | |
2389 if (src_lats->m_value_range.bottom_p ()) | |
2390 return dest_lat->set_to_bottom (); | |
2391 | |
2392 value_range vr; | |
1908 if (TREE_CODE_CLASS (operation) == tcc_unary) | 2393 if (TREE_CODE_CLASS (operation) == tcc_unary) |
1909 { | 2394 ipa_vr_operation_and_type_effects (&vr, |
1910 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 2395 &src_lats->m_value_range.m_vr, |
1911 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | 2396 operation, param_type, |
1912 tree operand_type = ipa_get_type (caller_info, src_idx); | 2397 operand_type); |
1913 struct ipcp_param_lattices *src_lats | 2398 /* A crude way to prevent unbounded number of value range updates |
1914 = ipa_get_parm_lattices (caller_info, src_idx); | 2399 in SCC components. We should allow limited number of updates within |
1915 | 2400 SCC, too. */ |
1916 if (src_lats->m_value_range.bottom_p ()) | 2401 else if (!ipa_edge_within_scc (cs)) |
1917 return dest_lat->set_to_bottom (); | 2402 { |
1918 value_range vr; | 2403 tree op = ipa_get_jf_pass_through_operand (jfunc); |
1919 if (ipa_vr_operation_and_type_effects (&vr, | 2404 value_range op_vr (op, op); |
1920 &src_lats->m_value_range.m_vr, | 2405 value_range op_res,res; |
1921 operation, param_type, | 2406 |
1922 operand_type)) | 2407 range_fold_binary_expr (&op_res, operation, operand_type, |
1923 return dest_lat->meet_with (&vr); | 2408 &src_lats->m_value_range.m_vr, &op_vr); |
2409 ipa_vr_operation_and_type_effects (&vr, | |
2410 &op_res, | |
2411 NOP_EXPR, param_type, | |
2412 operand_type); | |
2413 } | |
2414 if (!vr.undefined_p () && !vr.varying_p ()) | |
2415 { | |
2416 if (jfunc->m_vr) | |
2417 { | |
2418 value_range jvr; | |
2419 if (ipa_vr_operation_and_type_effects (&jvr, jfunc->m_vr, | |
2420 NOP_EXPR, | |
2421 param_type, | |
2422 jfunc->m_vr->type ())) | |
2423 vr.intersect (jvr); | |
2424 } | |
2425 return dest_lat->meet_with (&vr); | |
1924 } | 2426 } |
1925 } | 2427 } |
1926 else if (jfunc->type == IPA_JF_CONST) | 2428 else if (jfunc->type == IPA_JF_CONST) |
1927 { | 2429 { |
1928 tree val = ipa_get_jf_constant (jfunc); | 2430 tree val = ipa_get_jf_constant (jfunc); |
1930 { | 2432 { |
1931 val = fold_convert (param_type, val); | 2433 val = fold_convert (param_type, val); |
1932 if (TREE_OVERFLOW_P (val)) | 2434 if (TREE_OVERFLOW_P (val)) |
1933 val = drop_tree_overflow (val); | 2435 val = drop_tree_overflow (val); |
1934 | 2436 |
1935 value_range tmpvr (VR_RANGE, val, val); | 2437 value_range tmpvr (val, val); |
1936 return dest_lat->meet_with (&tmpvr); | 2438 return dest_lat->meet_with (&tmpvr); |
1937 } | 2439 } |
1938 } | 2440 } |
1939 | 2441 |
1940 value_range vr; | 2442 value_range vr; |
1951 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all | 2453 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all |
1952 other cases, return false). If there are no aggregate items, set | 2454 other cases, return false). If there are no aggregate items, set |
1953 aggs_by_ref to NEW_AGGS_BY_REF. */ | 2455 aggs_by_ref to NEW_AGGS_BY_REF. */ |
1954 | 2456 |
1955 static bool | 2457 static bool |
1956 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats, | 2458 set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats, |
1957 bool new_aggs_by_ref) | 2459 bool new_aggs_by_ref) |
1958 { | 2460 { |
1959 if (dest_plats->aggs) | 2461 if (dest_plats->aggs) |
1960 { | 2462 { |
1961 if (dest_plats->aggs_by_ref != new_aggs_by_ref) | 2463 if (dest_plats->aggs_by_ref != new_aggs_by_ref) |
1975 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize | 2477 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize |
1976 it with offset, size and contains_variable to PRE_EXISTING, and return true, | 2478 it with offset, size and contains_variable to PRE_EXISTING, and return true, |
1977 unless there are too many already. If there are two many, return false. If | 2479 unless there are too many already. If there are two many, return false. If |
1978 there are overlaps turn whole DEST_PLATS to bottom and return false. If any | 2480 there are overlaps turn whole DEST_PLATS to bottom and return false. If any |
1979 skipped lattices were newly marked as containing variable, set *CHANGE to | 2481 skipped lattices were newly marked as containing variable, set *CHANGE to |
1980 true. */ | 2482 true. MAX_AGG_ITEMS is the maximum number of lattices. */ |
1981 | 2483 |
1982 static bool | 2484 static bool |
1983 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats, | 2485 merge_agg_lats_step (class ipcp_param_lattices *dest_plats, |
1984 HOST_WIDE_INT offset, HOST_WIDE_INT val_size, | 2486 HOST_WIDE_INT offset, HOST_WIDE_INT val_size, |
1985 struct ipcp_agg_lattice ***aglat, | 2487 struct ipcp_agg_lattice ***aglat, |
1986 bool pre_existing, bool *change) | 2488 bool pre_existing, bool *change, int max_agg_items) |
1987 { | 2489 { |
1988 gcc_checking_assert (offset >= 0); | 2490 gcc_checking_assert (offset >= 0); |
1989 | 2491 |
1990 while (**aglat && (**aglat)->offset < offset) | 2492 while (**aglat && (**aglat)->offset < offset) |
1991 { | 2493 { |
1998 *aglat = &(**aglat)->next; | 2500 *aglat = &(**aglat)->next; |
1999 } | 2501 } |
2000 | 2502 |
2001 if (**aglat && (**aglat)->offset == offset) | 2503 if (**aglat && (**aglat)->offset == offset) |
2002 { | 2504 { |
2003 if ((**aglat)->size != val_size | 2505 if ((**aglat)->size != val_size) |
2004 || ((**aglat)->next | |
2005 && (**aglat)->next->offset < offset + val_size)) | |
2006 { | 2506 { |
2007 set_agg_lats_to_bottom (dest_plats); | 2507 set_agg_lats_to_bottom (dest_plats); |
2008 return false; | 2508 return false; |
2009 } | 2509 } |
2010 gcc_checking_assert (!(**aglat)->next | 2510 gcc_assert (!(**aglat)->next |
2011 || (**aglat)->next->offset >= offset + val_size); | 2511 || (**aglat)->next->offset >= offset + val_size); |
2012 return true; | 2512 return true; |
2013 } | 2513 } |
2014 else | 2514 else |
2015 { | 2515 { |
2016 struct ipcp_agg_lattice *new_al; | 2516 struct ipcp_agg_lattice *new_al; |
2018 if (**aglat && (**aglat)->offset < offset + val_size) | 2518 if (**aglat && (**aglat)->offset < offset + val_size) |
2019 { | 2519 { |
2020 set_agg_lats_to_bottom (dest_plats); | 2520 set_agg_lats_to_bottom (dest_plats); |
2021 return false; | 2521 return false; |
2022 } | 2522 } |
2023 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS)) | 2523 if (dest_plats->aggs_count == max_agg_items) |
2024 return false; | 2524 return false; |
2025 dest_plats->aggs_count++; | 2525 dest_plats->aggs_count++; |
2026 new_al = ipcp_agg_lattice_pool.allocate (); | 2526 new_al = ipcp_agg_lattice_pool.allocate (); |
2027 memset (new_al, 0, sizeof (*new_al)); | 2527 memset (new_al, 0, sizeof (*new_al)); |
2028 | 2528 |
2056 parameter used for lattice value sources. Return true if DEST_PLATS changed | 2556 parameter used for lattice value sources. Return true if DEST_PLATS changed |
2057 in any way. */ | 2557 in any way. */ |
2058 | 2558 |
2059 static bool | 2559 static bool |
2060 merge_aggregate_lattices (struct cgraph_edge *cs, | 2560 merge_aggregate_lattices (struct cgraph_edge *cs, |
2061 struct ipcp_param_lattices *dest_plats, | 2561 class ipcp_param_lattices *dest_plats, |
2062 struct ipcp_param_lattices *src_plats, | 2562 class ipcp_param_lattices *src_plats, |
2063 int src_idx, HOST_WIDE_INT offset_delta) | 2563 int src_idx, HOST_WIDE_INT offset_delta) |
2064 { | 2564 { |
2065 bool pre_existing = dest_plats->aggs != NULL; | 2565 bool pre_existing = dest_plats->aggs != NULL; |
2066 struct ipcp_agg_lattice **dst_aglat; | 2566 struct ipcp_agg_lattice **dst_aglat; |
2067 bool ret = false; | 2567 bool ret = false; |
2072 return set_agg_lats_contain_variable (dest_plats); | 2572 return set_agg_lats_contain_variable (dest_plats); |
2073 if (src_plats->aggs_contain_variable) | 2573 if (src_plats->aggs_contain_variable) |
2074 ret |= set_agg_lats_contain_variable (dest_plats); | 2574 ret |= set_agg_lats_contain_variable (dest_plats); |
2075 dst_aglat = &dest_plats->aggs; | 2575 dst_aglat = &dest_plats->aggs; |
2076 | 2576 |
2577 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl, | |
2578 param_ipa_max_agg_items); | |
2077 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs; | 2579 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs; |
2078 src_aglat; | 2580 src_aglat; |
2079 src_aglat = src_aglat->next) | 2581 src_aglat = src_aglat->next) |
2080 { | 2582 { |
2081 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta; | 2583 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta; |
2082 | 2584 |
2083 if (new_offset < 0) | 2585 if (new_offset < 0) |
2084 continue; | 2586 continue; |
2085 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size, | 2587 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size, |
2086 &dst_aglat, pre_existing, &ret)) | 2588 &dst_aglat, pre_existing, &ret, max_agg_items)) |
2087 { | 2589 { |
2088 struct ipcp_agg_lattice *new_al = *dst_aglat; | 2590 struct ipcp_agg_lattice *new_al = *dst_aglat; |
2089 | 2591 |
2090 dst_aglat = &(*dst_aglat)->next; | 2592 dst_aglat = &(*dst_aglat)->next; |
2091 if (src_aglat->bottom) | 2593 if (src_aglat->bottom) |
2111 /* Determine whether there is anything to propagate FROM SRC_PLATS through a | 2613 /* Determine whether there is anything to propagate FROM SRC_PLATS through a |
2112 pass-through JFUNC and if so, whether it has conform and conforms to the | 2614 pass-through JFUNC and if so, whether it has conform and conforms to the |
2113 rules about propagating values passed by reference. */ | 2615 rules about propagating values passed by reference. */ |
2114 | 2616 |
2115 static bool | 2617 static bool |
2116 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats, | 2618 agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats, |
2117 struct ipa_jump_func *jfunc) | 2619 struct ipa_jump_func *jfunc) |
2118 { | 2620 { |
2119 return src_plats->aggs | 2621 return src_plats->aggs |
2120 && (!src_plats->aggs_by_ref | 2622 && (!src_plats->aggs_by_ref |
2121 || ipa_get_jf_pass_through_agg_preserved (jfunc)); | 2623 || ipa_get_jf_pass_through_agg_preserved (jfunc)); |
2122 } | 2624 } |
2123 | 2625 |
2626 /* Propagate values through ITEM, jump function for a part of an aggregate, | |
2627 into corresponding aggregate lattice AGLAT. CS is the call graph edge | |
2628 associated with the jump function. Return true if AGLAT changed in any | |
2629 way. */ | |
2630 | |
2631 static bool | |
2632 propagate_aggregate_lattice (struct cgraph_edge *cs, | |
2633 struct ipa_agg_jf_item *item, | |
2634 struct ipcp_agg_lattice *aglat) | |
2635 { | |
2636 class ipa_node_params *caller_info; | |
2637 class ipcp_param_lattices *src_plats; | |
2638 struct ipcp_lattice<tree> *src_lat; | |
2639 HOST_WIDE_INT src_offset; | |
2640 int src_idx; | |
2641 tree load_type; | |
2642 bool ret; | |
2643 | |
2644 if (item->jftype == IPA_JF_CONST) | |
2645 { | |
2646 tree value = item->value.constant; | |
2647 | |
2648 gcc_checking_assert (is_gimple_ip_invariant (value)); | |
2649 return aglat->add_value (value, cs, NULL, 0); | |
2650 } | |
2651 | |
2652 gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH | |
2653 || item->jftype == IPA_JF_LOAD_AGG); | |
2654 | |
2655 caller_info = IPA_NODE_REF (cs->caller); | |
2656 src_idx = item->value.pass_through.formal_id; | |
2657 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | |
2658 | |
2659 if (item->jftype == IPA_JF_PASS_THROUGH) | |
2660 { | |
2661 load_type = NULL_TREE; | |
2662 src_lat = &src_plats->itself; | |
2663 src_offset = -1; | |
2664 } | |
2665 else | |
2666 { | |
2667 HOST_WIDE_INT load_offset = item->value.load_agg.offset; | |
2668 struct ipcp_agg_lattice *src_aglat; | |
2669 | |
2670 for (src_aglat = src_plats->aggs; src_aglat; src_aglat = src_aglat->next) | |
2671 if (src_aglat->offset >= load_offset) | |
2672 break; | |
2673 | |
2674 load_type = item->value.load_agg.type; | |
2675 if (!src_aglat | |
2676 || src_aglat->offset > load_offset | |
2677 || src_aglat->size != tree_to_shwi (TYPE_SIZE (load_type)) | |
2678 || src_plats->aggs_by_ref != item->value.load_agg.by_ref) | |
2679 return aglat->set_contains_variable (); | |
2680 | |
2681 src_lat = src_aglat; | |
2682 src_offset = load_offset; | |
2683 } | |
2684 | |
2685 if (src_lat->bottom | |
2686 || (!ipcp_versionable_function_p (cs->caller) | |
2687 && !src_lat->is_single_const ())) | |
2688 return aglat->set_contains_variable (); | |
2689 | |
2690 ret = propagate_vals_across_arith_jfunc (cs, | |
2691 item->value.pass_through.operation, | |
2692 load_type, | |
2693 item->value.pass_through.operand, | |
2694 src_lat, aglat, | |
2695 src_offset, | |
2696 src_idx, | |
2697 item->type); | |
2698 | |
2699 if (src_lat->contains_variable) | |
2700 ret |= aglat->set_contains_variable (); | |
2701 | |
2702 return ret; | |
2703 } | |
2704 | |
2124 /* Propagate scalar values across jump function JFUNC that is associated with | 2705 /* Propagate scalar values across jump function JFUNC that is associated with |
2125 edge CS and put the values into DEST_LAT. */ | 2706 edge CS and put the values into DEST_LAT. */ |
2126 | 2707 |
2127 static bool | 2708 static bool |
2128 propagate_aggs_across_jump_function (struct cgraph_edge *cs, | 2709 propagate_aggs_across_jump_function (struct cgraph_edge *cs, |
2129 struct ipa_jump_func *jfunc, | 2710 struct ipa_jump_func *jfunc, |
2130 struct ipcp_param_lattices *dest_plats) | 2711 class ipcp_param_lattices *dest_plats) |
2131 { | 2712 { |
2132 bool ret = false; | 2713 bool ret = false; |
2133 | 2714 |
2134 if (dest_plats->aggs_bottom) | 2715 if (dest_plats->aggs_bottom) |
2135 return false; | 2716 return false; |
2136 | 2717 |
2137 if (jfunc->type == IPA_JF_PASS_THROUGH | 2718 if (jfunc->type == IPA_JF_PASS_THROUGH |
2138 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | 2719 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) |
2139 { | 2720 { |
2140 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 2721 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
2141 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | 2722 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); |
2142 struct ipcp_param_lattices *src_plats; | 2723 class ipcp_param_lattices *src_plats; |
2143 | 2724 |
2144 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | 2725 src_plats = ipa_get_parm_lattices (caller_info, src_idx); |
2145 if (agg_pass_through_permissible_p (src_plats, jfunc)) | 2726 if (agg_pass_through_permissible_p (src_plats, jfunc)) |
2146 { | 2727 { |
2147 /* Currently we do not produce clobber aggregate jump | 2728 /* Currently we do not produce clobber aggregate jump |
2154 ret |= set_agg_lats_contain_variable (dest_plats); | 2735 ret |= set_agg_lats_contain_variable (dest_plats); |
2155 } | 2736 } |
2156 else if (jfunc->type == IPA_JF_ANCESTOR | 2737 else if (jfunc->type == IPA_JF_ANCESTOR |
2157 && ipa_get_jf_ancestor_agg_preserved (jfunc)) | 2738 && ipa_get_jf_ancestor_agg_preserved (jfunc)) |
2158 { | 2739 { |
2159 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 2740 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
2160 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | 2741 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); |
2161 struct ipcp_param_lattices *src_plats; | 2742 class ipcp_param_lattices *src_plats; |
2162 | 2743 |
2163 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | 2744 src_plats = ipa_get_parm_lattices (caller_info, src_idx); |
2164 if (src_plats->aggs && src_plats->aggs_by_ref) | 2745 if (src_plats->aggs && src_plats->aggs_by_ref) |
2165 { | 2746 { |
2166 /* Currently we do not produce clobber aggregate jump | 2747 /* Currently we do not produce clobber aggregate jump |
2182 int i; | 2763 int i; |
2183 | 2764 |
2184 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref)) | 2765 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref)) |
2185 return true; | 2766 return true; |
2186 | 2767 |
2768 int max_agg_items = opt_for_fn (cs->callee->function_symbol ()->decl, | |
2769 param_ipa_max_agg_items); | |
2187 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item) | 2770 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item) |
2188 { | 2771 { |
2189 HOST_WIDE_INT val_size; | 2772 HOST_WIDE_INT val_size; |
2190 | 2773 |
2191 if (item->offset < 0) | 2774 if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN) |
2192 continue; | 2775 continue; |
2193 gcc_checking_assert (is_gimple_ip_invariant (item->value)); | 2776 val_size = tree_to_shwi (TYPE_SIZE (item->type)); |
2194 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value))); | |
2195 | 2777 |
2196 if (merge_agg_lats_step (dest_plats, item->offset, val_size, | 2778 if (merge_agg_lats_step (dest_plats, item->offset, val_size, |
2197 &aglat, pre_existing, &ret)) | 2779 &aglat, pre_existing, &ret, max_agg_items)) |
2198 { | 2780 { |
2199 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0); | 2781 ret |= propagate_aggregate_lattice (cs, item, *aglat); |
2200 aglat = &(*aglat)->next; | 2782 aglat = &(*aglat)->next; |
2201 } | 2783 } |
2202 else if (dest_plats->aggs_bottom) | 2784 else if (dest_plats->aggs_bottom) |
2203 return true; | 2785 return true; |
2204 } | 2786 } |
2227 caller. */ | 2809 caller. */ |
2228 | 2810 |
2229 static bool | 2811 static bool |
2230 propagate_constants_across_call (struct cgraph_edge *cs) | 2812 propagate_constants_across_call (struct cgraph_edge *cs) |
2231 { | 2813 { |
2232 struct ipa_node_params *callee_info; | 2814 class ipa_node_params *callee_info; |
2233 enum availability availability; | 2815 enum availability availability; |
2234 cgraph_node *callee; | 2816 cgraph_node *callee; |
2235 struct ipa_edge_args *args; | 2817 class ipa_edge_args *args; |
2236 bool ret = false; | 2818 bool ret = false; |
2237 int i, args_count, parms_count; | 2819 int i, args_count, parms_count; |
2238 | 2820 |
2239 callee = cs->callee->function_symbol (&availability); | 2821 callee = cs->callee->function_symbol (&availability); |
2240 if (!callee->definition) | 2822 if (!callee->definition) |
2241 return false; | 2823 return false; |
2242 gcc_checking_assert (callee->has_gimple_body_p ()); | 2824 gcc_checking_assert (callee->has_gimple_body_p ()); |
2243 callee_info = IPA_NODE_REF (callee); | 2825 callee_info = IPA_NODE_REF (callee); |
2826 if (!callee_info) | |
2827 return false; | |
2244 | 2828 |
2245 args = IPA_EDGE_REF (cs); | 2829 args = IPA_EDGE_REF (cs); |
2246 args_count = ipa_get_cs_argument_count (args); | |
2247 parms_count = ipa_get_param_count (callee_info); | 2830 parms_count = ipa_get_param_count (callee_info); |
2248 if (parms_count == 0) | 2831 if (parms_count == 0) |
2249 return false; | 2832 return false; |
2833 if (!args | |
2834 || !opt_for_fn (cs->caller->decl, flag_ipa_cp) | |
2835 || !opt_for_fn (cs->caller->decl, optimize)) | |
2836 { | |
2837 for (i = 0; i < parms_count; i++) | |
2838 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, | |
2839 i)); | |
2840 return ret; | |
2841 } | |
2842 args_count = ipa_get_cs_argument_count (args); | |
2250 | 2843 |
2251 /* If this call goes through a thunk we must not propagate to the first (0th) | 2844 /* If this call goes through a thunk we must not propagate to the first (0th) |
2252 parameter. However, we might need to uncover a thunk from below a series | 2845 parameter. However, we might need to uncover a thunk from below a series |
2253 of aliases first. */ | 2846 of aliases first. */ |
2254 if (call_passes_through_thunk_p (cs)) | 2847 if (call_passes_through_thunk_p (cs)) |
2261 i = 0; | 2854 i = 0; |
2262 | 2855 |
2263 for (; (i < args_count) && (i < parms_count); i++) | 2856 for (; (i < args_count) && (i < parms_count); i++) |
2264 { | 2857 { |
2265 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); | 2858 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); |
2266 struct ipcp_param_lattices *dest_plats; | 2859 class ipcp_param_lattices *dest_plats; |
2267 tree param_type = ipa_get_type (callee_info, i); | 2860 tree param_type = ipa_get_type (callee_info, i); |
2268 | 2861 |
2269 dest_plats = ipa_get_parm_lattices (callee_info, i); | 2862 dest_plats = ipa_get_parm_lattices (callee_info, i); |
2270 if (availability == AVAIL_INTERPOSABLE) | 2863 if (availability == AVAIL_INTERPOSABLE) |
2271 ret |= set_all_contains_variable (dest_plats); | 2864 ret |= set_all_contains_variable (dest_plats); |
2300 | 2893 |
2301 static tree | 2894 static tree |
2302 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, | 2895 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, |
2303 vec<tree> known_csts, | 2896 vec<tree> known_csts, |
2304 vec<ipa_polymorphic_call_context> known_contexts, | 2897 vec<ipa_polymorphic_call_context> known_contexts, |
2305 vec<ipa_agg_jump_function_p> known_aggs, | 2898 vec<ipa_agg_value_set> known_aggs, |
2306 struct ipa_agg_replacement_value *agg_reps, | 2899 struct ipa_agg_replacement_value *agg_reps, |
2307 bool *speculative) | 2900 bool *speculative) |
2308 { | 2901 { |
2309 int param_index = ie->indirect_info->param_index; | 2902 int param_index = ie->indirect_info->param_index; |
2310 HOST_WIDE_INT anc_offset; | 2903 HOST_WIDE_INT anc_offset; |
2311 tree t; | 2904 tree t = NULL; |
2312 tree target = NULL; | 2905 tree target = NULL; |
2313 | 2906 |
2314 *speculative = false; | 2907 *speculative = false; |
2315 | 2908 |
2316 if (param_index == -1 | 2909 if (param_index == -1) |
2317 || known_csts.length () <= (unsigned int) param_index) | |
2318 return NULL_TREE; | 2910 return NULL_TREE; |
2319 | 2911 |
2320 if (!ie->indirect_info->polymorphic) | 2912 if (!ie->indirect_info->polymorphic) |
2321 { | 2913 { |
2322 tree t; | 2914 tree t = NULL; |
2323 | 2915 |
2324 if (ie->indirect_info->agg_contents) | 2916 if (ie->indirect_info->agg_contents) |
2325 { | 2917 { |
2326 t = NULL; | 2918 t = NULL; |
2327 if (agg_reps && ie->indirect_info->guaranteed_unmodified) | 2919 if (agg_reps && ie->indirect_info->guaranteed_unmodified) |
2338 agg_reps = agg_reps->next; | 2930 agg_reps = agg_reps->next; |
2339 } | 2931 } |
2340 } | 2932 } |
2341 if (!t) | 2933 if (!t) |
2342 { | 2934 { |
2343 struct ipa_agg_jump_function *agg; | 2935 struct ipa_agg_value_set *agg; |
2344 if (known_aggs.length () > (unsigned int) param_index) | 2936 if (known_aggs.length () > (unsigned int) param_index) |
2345 agg = known_aggs[param_index]; | 2937 agg = &known_aggs[param_index]; |
2346 else | 2938 else |
2347 agg = NULL; | 2939 agg = NULL; |
2348 bool from_global_constant; | 2940 bool from_global_constant; |
2349 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], | 2941 t = ipa_find_agg_cst_for_param (agg, |
2942 (unsigned) param_index | |
2943 < known_csts.length () | |
2944 ? known_csts[param_index] | |
2945 : NULL, | |
2350 ie->indirect_info->offset, | 2946 ie->indirect_info->offset, |
2351 ie->indirect_info->by_ref, | 2947 ie->indirect_info->by_ref, |
2352 &from_global_constant); | 2948 &from_global_constant); |
2353 if (t | 2949 if (t |
2354 && !from_global_constant | 2950 && !from_global_constant |
2355 && !ie->indirect_info->guaranteed_unmodified) | 2951 && !ie->indirect_info->guaranteed_unmodified) |
2356 t = NULL_TREE; | 2952 t = NULL_TREE; |
2357 } | 2953 } |
2358 } | 2954 } |
2359 else | 2955 else if ((unsigned) param_index < known_csts.length ()) |
2360 t = known_csts[param_index]; | 2956 t = known_csts[param_index]; |
2361 | 2957 |
2362 if (t | 2958 if (t |
2363 && TREE_CODE (t) == ADDR_EXPR | 2959 && TREE_CODE (t) == ADDR_EXPR |
2364 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL) | 2960 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL) |
2373 gcc_assert (!ie->indirect_info->agg_contents); | 2969 gcc_assert (!ie->indirect_info->agg_contents); |
2374 anc_offset = ie->indirect_info->offset; | 2970 anc_offset = ie->indirect_info->offset; |
2375 | 2971 |
2376 t = NULL; | 2972 t = NULL; |
2377 | 2973 |
2378 /* Try to work out value of virtual table pointer value in replacemnets. */ | 2974 /* Try to work out value of virtual table pointer value in replacements. */ |
2379 if (!t && agg_reps && !ie->indirect_info->by_ref) | 2975 if (!t && agg_reps && !ie->indirect_info->by_ref) |
2380 { | 2976 { |
2381 while (agg_reps) | 2977 while (agg_reps) |
2382 { | 2978 { |
2383 if (agg_reps->index == param_index | 2979 if (agg_reps->index == param_index |
2394 /* Try to work out value of virtual table pointer value in known | 2990 /* Try to work out value of virtual table pointer value in known |
2395 aggregate values. */ | 2991 aggregate values. */ |
2396 if (!t && known_aggs.length () > (unsigned int) param_index | 2992 if (!t && known_aggs.length () > (unsigned int) param_index |
2397 && !ie->indirect_info->by_ref) | 2993 && !ie->indirect_info->by_ref) |
2398 { | 2994 { |
2399 struct ipa_agg_jump_function *agg; | 2995 struct ipa_agg_value_set *agg = &known_aggs[param_index]; |
2400 agg = known_aggs[param_index]; | 2996 t = ipa_find_agg_cst_for_param (agg, |
2401 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], | 2997 (unsigned) param_index |
2998 < known_csts.length () | |
2999 ? known_csts[param_index] : NULL, | |
2402 ie->indirect_info->offset, true); | 3000 ie->indirect_info->offset, true); |
2403 } | 3001 } |
2404 | 3002 |
2405 /* If we found the virtual table pointer, lookup the target. */ | 3003 /* If we found the virtual table pointer, lookup the target. */ |
2406 if (t) | 3004 if (t) |
2413 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token, | 3011 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token, |
2414 vtable, offset, &can_refer); | 3012 vtable, offset, &can_refer); |
2415 if (can_refer) | 3013 if (can_refer) |
2416 { | 3014 { |
2417 if (!target | 3015 if (!target |
2418 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE | 3016 || fndecl_built_in_p (target, BUILT_IN_UNREACHABLE) |
2419 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE) | |
2420 || !possible_polymorphic_call_target_p | 3017 || !possible_polymorphic_call_target_p |
2421 (ie, cgraph_node::get (target))) | 3018 (ie, cgraph_node::get (target))) |
2422 { | 3019 { |
2423 /* Do not speculate builtin_unreachable, it is stupid! */ | 3020 /* Do not speculate builtin_unreachable, it is stupid! */ |
2424 if (ie->indirect_info->vptr_changed) | 3021 if (ie->indirect_info->vptr_changed) |
2431 } | 3028 } |
2432 } | 3029 } |
2433 } | 3030 } |
2434 | 3031 |
2435 /* Do we know the constant value of pointer? */ | 3032 /* Do we know the constant value of pointer? */ |
2436 if (!t) | 3033 if (!t && (unsigned) param_index < known_csts.length ()) |
2437 t = known_csts[param_index]; | 3034 t = known_csts[param_index]; |
2438 | 3035 |
2439 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO); | 3036 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO); |
2440 | 3037 |
2441 ipa_polymorphic_call_context context; | 3038 ipa_polymorphic_call_context context; |
2518 | 3115 |
2519 tree | 3116 tree |
2520 ipa_get_indirect_edge_target (struct cgraph_edge *ie, | 3117 ipa_get_indirect_edge_target (struct cgraph_edge *ie, |
2521 vec<tree> known_csts, | 3118 vec<tree> known_csts, |
2522 vec<ipa_polymorphic_call_context> known_contexts, | 3119 vec<ipa_polymorphic_call_context> known_contexts, |
2523 vec<ipa_agg_jump_function_p> known_aggs, | 3120 vec<ipa_agg_value_set> known_aggs, |
2524 bool *speculative) | 3121 bool *speculative) |
2525 { | 3122 { |
2526 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, | 3123 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, |
2527 known_aggs, NULL, speculative); | 3124 known_aggs, NULL, speculative); |
2528 } | 3125 } |
2532 | 3129 |
2533 static int | 3130 static int |
2534 devirtualization_time_bonus (struct cgraph_node *node, | 3131 devirtualization_time_bonus (struct cgraph_node *node, |
2535 vec<tree> known_csts, | 3132 vec<tree> known_csts, |
2536 vec<ipa_polymorphic_call_context> known_contexts, | 3133 vec<ipa_polymorphic_call_context> known_contexts, |
2537 vec<ipa_agg_jump_function_p> known_aggs) | 3134 vec<ipa_agg_value_set> known_aggs) |
2538 { | 3135 { |
2539 struct cgraph_edge *ie; | 3136 struct cgraph_edge *ie; |
2540 int res = 0; | 3137 int res = 0; |
2541 | 3138 |
2542 for (ie = node->indirect_calls; ie; ie = ie->next_callee) | 3139 for (ie = node->indirect_calls; ie; ie = ie->next_callee) |
2543 { | 3140 { |
2544 struct cgraph_node *callee; | 3141 struct cgraph_node *callee; |
2545 struct ipa_fn_summary *isummary; | 3142 class ipa_fn_summary *isummary; |
2546 enum availability avail; | 3143 enum availability avail; |
2547 tree target; | 3144 tree target; |
2548 bool speculative; | 3145 bool speculative; |
2549 | 3146 |
2550 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts, | 3147 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts, |
2559 continue; | 3156 continue; |
2560 callee = callee->function_symbol (&avail); | 3157 callee = callee->function_symbol (&avail); |
2561 if (avail < AVAIL_AVAILABLE) | 3158 if (avail < AVAIL_AVAILABLE) |
2562 continue; | 3159 continue; |
2563 isummary = ipa_fn_summaries->get (callee); | 3160 isummary = ipa_fn_summaries->get (callee); |
2564 if (!isummary->inlinable) | 3161 if (!isummary || !isummary->inlinable) |
2565 continue; | 3162 continue; |
2566 | 3163 |
3164 int size = ipa_size_summaries->get (callee)->size; | |
2567 /* FIXME: The values below need re-considering and perhaps also | 3165 /* FIXME: The values below need re-considering and perhaps also |
2568 integrating into the cost metrics, at lest in some very basic way. */ | 3166 integrating into the cost metrics, at lest in some very basic way. */ |
2569 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4) | 3167 int max_inline_insns_auto |
3168 = opt_for_fn (callee->decl, param_max_inline_insns_auto); | |
3169 if (size <= max_inline_insns_auto / 4) | |
2570 res += 31 / ((int)speculative + 1); | 3170 res += 31 / ((int)speculative + 1); |
2571 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2) | 3171 else if (size <= max_inline_insns_auto / 2) |
2572 res += 15 / ((int)speculative + 1); | 3172 res += 15 / ((int)speculative + 1); |
2573 else if (isummary->size <= MAX_INLINE_INSNS_AUTO | 3173 else if (size <= max_inline_insns_auto |
2574 || DECL_DECLARED_INLINE_P (callee->decl)) | 3174 || DECL_DECLARED_INLINE_P (callee->decl)) |
2575 res += 7 / ((int)speculative + 1); | 3175 res += 7 / ((int)speculative + 1); |
2576 } | 3176 } |
2577 | 3177 |
2578 return res; | 3178 return res; |
2579 } | 3179 } |
2580 | 3180 |
2581 /* Return time bonus incurred because of HINTS. */ | 3181 /* Return time bonus incurred because of HINTS. */ |
2582 | 3182 |
2583 static int | 3183 static int |
2584 hint_time_bonus (ipa_hints hints) | 3184 hint_time_bonus (cgraph_node *node, ipa_hints hints) |
2585 { | 3185 { |
2586 int result = 0; | 3186 int result = 0; |
2587 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) | 3187 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) |
2588 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS); | 3188 result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus); |
2589 if (hints & INLINE_HINT_array_index) | |
2590 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS); | |
2591 return result; | 3189 return result; |
2592 } | 3190 } |
2593 | 3191 |
2594 /* If there is a reason to penalize the function described by INFO in the | 3192 /* If there is a reason to penalize the function described by INFO in the |
2595 cloning goodness evaluation, do so. */ | 3193 cloning goodness evaluation, do so. */ |
2596 | 3194 |
2597 static inline int64_t | 3195 static inline int64_t |
2598 incorporate_penalties (ipa_node_params *info, int64_t evaluation) | 3196 incorporate_penalties (cgraph_node *node, ipa_node_params *info, |
2599 { | 3197 int64_t evaluation) |
2600 if (info->node_within_scc) | 3198 { |
3199 if (info->node_within_scc && !info->node_is_self_scc) | |
2601 evaluation = (evaluation | 3200 evaluation = (evaluation |
2602 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100; | 3201 * (100 - opt_for_fn (node->decl, |
3202 param_ipa_cp_recursion_penalty))) / 100; | |
2603 | 3203 |
2604 if (info->node_calling_single_call) | 3204 if (info->node_calling_single_call) |
2605 evaluation = (evaluation | 3205 evaluation = (evaluation |
2606 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY))) | 3206 * (100 - opt_for_fn (node->decl, |
3207 param_ipa_cp_single_call_penalty))) | |
2607 / 100; | 3208 / 100; |
2608 | 3209 |
2609 return evaluation; | 3210 return evaluation; |
2610 } | 3211 } |
2611 | 3212 |
2622 || node->optimize_for_size_p ()) | 3223 || node->optimize_for_size_p ()) |
2623 return false; | 3224 return false; |
2624 | 3225 |
2625 gcc_assert (size_cost > 0); | 3226 gcc_assert (size_cost > 0); |
2626 | 3227 |
2627 struct ipa_node_params *info = IPA_NODE_REF (node); | 3228 class ipa_node_params *info = IPA_NODE_REF (node); |
3229 int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold); | |
2628 if (max_count > profile_count::zero ()) | 3230 if (max_count > profile_count::zero ()) |
2629 { | 3231 { |
2630 int factor = RDIV (count_sum.probability_in | 3232 int factor = RDIV (count_sum.probability_in |
2631 (max_count).to_reg_br_prob_base () | 3233 (max_count).to_reg_br_prob_base () |
2632 * 1000, REG_BR_PROB_BASE); | 3234 * 1000, REG_BR_PROB_BASE); |
2633 int64_t evaluation = (((int64_t) time_benefit * factor) | 3235 int64_t evaluation = (((int64_t) time_benefit * factor) |
2634 / size_cost); | 3236 / size_cost); |
2635 evaluation = incorporate_penalties (info, evaluation); | 3237 evaluation = incorporate_penalties (node, info, evaluation); |
2636 | 3238 |
2637 if (dump_file && (dump_flags & TDF_DETAILS)) | 3239 if (dump_file && (dump_flags & TDF_DETAILS)) |
2638 { | 3240 { |
2639 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " | 3241 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " |
2640 "size: %i, count_sum: ", time_benefit, size_cost); | 3242 "size: %i, count_sum: ", time_benefit, size_cost); |
2641 count_sum.dump (dump_file); | 3243 count_sum.dump (dump_file); |
2642 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64 | 3244 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64 |
2643 ", threshold: %i\n", | 3245 ", threshold: %i\n", |
2644 info->node_within_scc ? ", scc" : "", | 3246 info->node_within_scc |
3247 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "", | |
2645 info->node_calling_single_call ? ", single_call" : "", | 3248 info->node_calling_single_call ? ", single_call" : "", |
2646 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); | 3249 evaluation, eval_threshold); |
2647 } | 3250 } |
2648 | 3251 |
2649 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); | 3252 return evaluation >= eval_threshold; |
2650 } | 3253 } |
2651 else | 3254 else |
2652 { | 3255 { |
2653 int64_t evaluation = (((int64_t) time_benefit * freq_sum) | 3256 int64_t evaluation = (((int64_t) time_benefit * freq_sum) |
2654 / size_cost); | 3257 / size_cost); |
2655 evaluation = incorporate_penalties (info, evaluation); | 3258 evaluation = incorporate_penalties (node, info, evaluation); |
2656 | 3259 |
2657 if (dump_file && (dump_flags & TDF_DETAILS)) | 3260 if (dump_file && (dump_flags & TDF_DETAILS)) |
2658 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " | 3261 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " |
2659 "size: %i, freq_sum: %i%s%s) -> evaluation: " | 3262 "size: %i, freq_sum: %i%s%s) -> evaluation: " |
2660 "%" PRId64 ", threshold: %i\n", | 3263 "%" PRId64 ", threshold: %i\n", |
2661 time_benefit, size_cost, freq_sum, | 3264 time_benefit, size_cost, freq_sum, |
2662 info->node_within_scc ? ", scc" : "", | 3265 info->node_within_scc |
3266 ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "", | |
2663 info->node_calling_single_call ? ", single_call" : "", | 3267 info->node_calling_single_call ? ", single_call" : "", |
2664 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); | 3268 evaluation, eval_threshold); |
2665 | 3269 |
2666 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); | 3270 return evaluation >= eval_threshold; |
2667 } | 3271 } |
2668 } | 3272 } |
2669 | 3273 |
2670 /* Return all context independent values from aggregate lattices in PLATS in a | 3274 /* Return all context independent values from aggregate lattices in PLATS in a |
2671 vector. Return NULL if there are none. */ | 3275 vector. Return NULL if there are none. */ |
2672 | 3276 |
2673 static vec<ipa_agg_jf_item, va_gc> * | 3277 static vec<ipa_agg_value> |
2674 context_independent_aggregate_values (struct ipcp_param_lattices *plats) | 3278 context_independent_aggregate_values (class ipcp_param_lattices *plats) |
2675 { | 3279 { |
2676 vec<ipa_agg_jf_item, va_gc> *res = NULL; | 3280 vec<ipa_agg_value> res = vNULL; |
2677 | 3281 |
2678 if (plats->aggs_bottom | 3282 if (plats->aggs_bottom |
2679 || plats->aggs_contain_variable | 3283 || plats->aggs_contain_variable |
2680 || plats->aggs_count == 0) | 3284 || plats->aggs_count == 0) |
2681 return NULL; | 3285 return vNULL; |
2682 | 3286 |
2683 for (struct ipcp_agg_lattice *aglat = plats->aggs; | 3287 for (struct ipcp_agg_lattice *aglat = plats->aggs; |
2684 aglat; | 3288 aglat; |
2685 aglat = aglat->next) | 3289 aglat = aglat->next) |
2686 if (aglat->is_single_const ()) | 3290 if (aglat->is_single_const ()) |
2687 { | 3291 { |
2688 struct ipa_agg_jf_item item; | 3292 struct ipa_agg_value item; |
2689 item.offset = aglat->offset; | 3293 item.offset = aglat->offset; |
2690 item.value = aglat->values->value; | 3294 item.value = aglat->values->value; |
2691 vec_safe_push (res, item); | 3295 res.safe_push (item); |
2692 } | 3296 } |
2693 return res; | 3297 return res; |
2694 } | 3298 } |
2695 | 3299 |
2696 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and | 3300 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and |
2698 context. INFO describes the function. If REMOVABLE_PARAMS_COST is | 3302 context. INFO describes the function. If REMOVABLE_PARAMS_COST is |
2699 non-NULL, the movement cost of all removable parameters will be stored in | 3303 non-NULL, the movement cost of all removable parameters will be stored in |
2700 it. */ | 3304 it. */ |
2701 | 3305 |
2702 static bool | 3306 static bool |
2703 gather_context_independent_values (struct ipa_node_params *info, | 3307 gather_context_independent_values (class ipa_node_params *info, |
2704 vec<tree> *known_csts, | 3308 vec<tree> *known_csts, |
2705 vec<ipa_polymorphic_call_context> | 3309 vec<ipa_polymorphic_call_context> |
2706 *known_contexts, | 3310 *known_contexts, |
2707 vec<ipa_agg_jump_function> *known_aggs, | 3311 vec<ipa_agg_value_set> *known_aggs, |
2708 int *removable_params_cost) | 3312 int *removable_params_cost) |
2709 { | 3313 { |
2710 int i, count = ipa_get_param_count (info); | 3314 int i, count = ipa_get_param_count (info); |
2711 bool ret = false; | 3315 bool ret = false; |
2712 | 3316 |
2723 if (removable_params_cost) | 3327 if (removable_params_cost) |
2724 *removable_params_cost = 0; | 3328 *removable_params_cost = 0; |
2725 | 3329 |
2726 for (i = 0; i < count; i++) | 3330 for (i = 0; i < count; i++) |
2727 { | 3331 { |
2728 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 3332 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
2729 ipcp_lattice<tree> *lat = &plats->itself; | 3333 ipcp_lattice<tree> *lat = &plats->itself; |
2730 | 3334 |
2731 if (lat->is_single_const ()) | 3335 if (lat->is_single_const ()) |
2732 { | 3336 { |
2733 ipcp_value<tree> *val = lat->values; | 3337 ipcp_value<tree> *val = lat->values; |
2752 if (ctxlat->is_single_const ()) | 3356 if (ctxlat->is_single_const ()) |
2753 (*known_contexts)[i] = ctxlat->values->value; | 3357 (*known_contexts)[i] = ctxlat->values->value; |
2754 | 3358 |
2755 if (known_aggs) | 3359 if (known_aggs) |
2756 { | 3360 { |
2757 vec<ipa_agg_jf_item, va_gc> *agg_items; | 3361 vec<ipa_agg_value> agg_items; |
2758 struct ipa_agg_jump_function *ajf; | 3362 struct ipa_agg_value_set *agg; |
2759 | 3363 |
2760 agg_items = context_independent_aggregate_values (plats); | 3364 agg_items = context_independent_aggregate_values (plats); |
2761 ajf = &(*known_aggs)[i]; | 3365 agg = &(*known_aggs)[i]; |
2762 ajf->items = agg_items; | 3366 agg->items = agg_items; |
2763 ajf->by_ref = plats->aggs_by_ref; | 3367 agg->by_ref = plats->aggs_by_ref; |
2764 ret |= agg_items != NULL; | 3368 ret |= !agg_items.is_empty (); |
2765 } | 3369 } |
2766 } | 3370 } |
2767 | 3371 |
2768 return ret; | |
2769 } | |
2770 | |
2771 /* The current interface in ipa-inline-analysis requires a pointer vector. | |
2772 Create it. | |
2773 | |
2774 FIXME: That interface should be re-worked, this is slightly silly. Still, | |
2775 I'd like to discuss how to change it first and this demonstrates the | |
2776 issue. */ | |
2777 | |
2778 static vec<ipa_agg_jump_function_p> | |
2779 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs) | |
2780 { | |
2781 vec<ipa_agg_jump_function_p> ret; | |
2782 struct ipa_agg_jump_function *ajf; | |
2783 int i; | |
2784 | |
2785 ret.create (known_aggs.length ()); | |
2786 FOR_EACH_VEC_ELT (known_aggs, i, ajf) | |
2787 ret.quick_push (ajf); | |
2788 return ret; | 3372 return ret; |
2789 } | 3373 } |
2790 | 3374 |
2791 /* Perform time and size measurement of NODE with the context given in | 3375 /* Perform time and size measurement of NODE with the context given in |
2792 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost | 3376 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost |
2795 movement of the considered parameter and store it into VAL. */ | 3379 movement of the considered parameter and store it into VAL. */ |
2796 | 3380 |
2797 static void | 3381 static void |
2798 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, | 3382 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, |
2799 vec<ipa_polymorphic_call_context> known_contexts, | 3383 vec<ipa_polymorphic_call_context> known_contexts, |
2800 vec<ipa_agg_jump_function_p> known_aggs_ptrs, | 3384 vec<ipa_agg_value_set> known_aggs, |
2801 int removable_params_cost, | 3385 int removable_params_cost, |
2802 int est_move_cost, ipcp_value_base *val) | 3386 int est_move_cost, ipcp_value_base *val) |
2803 { | 3387 { |
2804 int size, time_benefit; | 3388 int size, time_benefit; |
2805 sreal time, base_time; | 3389 sreal time, base_time; |
2806 ipa_hints hints; | 3390 ipa_hints hints; |
2807 | 3391 |
2808 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, | 3392 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, |
2809 known_aggs_ptrs, &size, &time, | 3393 known_aggs, &size, &time, |
2810 &base_time, &hints); | 3394 &base_time, &hints); |
2811 base_time -= time; | 3395 base_time -= time; |
2812 if (base_time > 65535) | 3396 if (base_time > 65535) |
2813 base_time = 65535; | 3397 base_time = 65535; |
2814 time_benefit = base_time.to_int () | 3398 |
2815 + devirtualization_time_bonus (node, known_csts, known_contexts, | 3399 /* Extern inline functions have no cloning local time benefits because they |
2816 known_aggs_ptrs) | 3400 will be inlined anyway. The only reason to clone them is if it enables |
2817 + hint_time_bonus (hints) | 3401 optimization in any of the functions they call. */ |
2818 + removable_params_cost + est_move_cost; | 3402 if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl)) |
3403 time_benefit = 0; | |
3404 else | |
3405 time_benefit = base_time.to_int () | |
3406 + devirtualization_time_bonus (node, known_csts, known_contexts, | |
3407 known_aggs) | |
3408 + hint_time_bonus (node, hints) | |
3409 + removable_params_cost + est_move_cost; | |
2819 | 3410 |
2820 gcc_checking_assert (size >=0); | 3411 gcc_checking_assert (size >=0); |
2821 /* The inliner-heuristics based estimates may think that in certain | 3412 /* The inliner-heuristics based estimates may think that in certain |
2822 contexts some functions do not have any size at all but we want | 3413 contexts some functions do not have any size at all but we want |
2823 all specializations to have at least a tiny cost, not least not to | 3414 all specializations to have at least a tiny cost, not least not to |
2827 | 3418 |
2828 val->local_time_benefit = time_benefit; | 3419 val->local_time_benefit = time_benefit; |
2829 val->local_size_cost = size; | 3420 val->local_size_cost = size; |
2830 } | 3421 } |
2831 | 3422 |
3423 /* Get the overall limit oof growth based on parameters extracted from growth. | |
3424 it does not really make sense to mix functions with different overall growth | |
3425 limits but it is possible and if it happens, we do not want to select one | |
3426 limit at random. */ | |
3427 | |
3428 static long | |
3429 get_max_overall_size (cgraph_node *node) | |
3430 { | |
3431 long max_new_size = orig_overall_size; | |
3432 long large_unit = opt_for_fn (node->decl, param_large_unit_insns); | |
3433 if (max_new_size < large_unit) | |
3434 max_new_size = large_unit; | |
3435 int unit_growth = opt_for_fn (node->decl, param_ipa_cp_unit_growth); | |
3436 max_new_size += max_new_size * unit_growth / 100 + 1; | |
3437 return max_new_size; | |
3438 } | |
3439 | |
2832 /* Iterate over known values of parameters of NODE and estimate the local | 3440 /* Iterate over known values of parameters of NODE and estimate the local |
2833 effects in terms of time and size they have. */ | 3441 effects in terms of time and size they have. */ |
2834 | 3442 |
2835 static void | 3443 static void |
2836 estimate_local_effects (struct cgraph_node *node) | 3444 estimate_local_effects (struct cgraph_node *node) |
2837 { | 3445 { |
2838 struct ipa_node_params *info = IPA_NODE_REF (node); | 3446 class ipa_node_params *info = IPA_NODE_REF (node); |
2839 int i, count = ipa_get_param_count (info); | 3447 int i, count = ipa_get_param_count (info); |
2840 vec<tree> known_csts; | 3448 vec<tree> known_csts; |
2841 vec<ipa_polymorphic_call_context> known_contexts; | 3449 vec<ipa_polymorphic_call_context> known_contexts; |
2842 vec<ipa_agg_jump_function> known_aggs; | 3450 vec<ipa_agg_value_set> known_aggs; |
2843 vec<ipa_agg_jump_function_p> known_aggs_ptrs; | |
2844 bool always_const; | 3451 bool always_const; |
2845 int removable_params_cost; | 3452 int removable_params_cost; |
2846 | 3453 |
2847 if (!count || !ipcp_versionable_function_p (node)) | 3454 if (!count || !ipcp_versionable_function_p (node)) |
2848 return; | 3455 return; |
2851 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ()); | 3458 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ()); |
2852 | 3459 |
2853 always_const = gather_context_independent_values (info, &known_csts, | 3460 always_const = gather_context_independent_values (info, &known_csts, |
2854 &known_contexts, &known_aggs, | 3461 &known_contexts, &known_aggs, |
2855 &removable_params_cost); | 3462 &removable_params_cost); |
2856 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs); | |
2857 int devirt_bonus = devirtualization_time_bonus (node, known_csts, | 3463 int devirt_bonus = devirtualization_time_bonus (node, known_csts, |
2858 known_contexts, known_aggs_ptrs); | 3464 known_contexts, known_aggs); |
2859 if (always_const || devirt_bonus | 3465 if (always_const || devirt_bonus |
2860 || (removable_params_cost && node->local.can_change_signature)) | 3466 || (removable_params_cost && node->can_change_signature)) |
2861 { | 3467 { |
2862 struct caller_statistics stats; | 3468 struct caller_statistics stats; |
2863 ipa_hints hints; | 3469 ipa_hints hints; |
2864 sreal time, base_time; | 3470 sreal time, base_time; |
2865 int size; | 3471 int size; |
2866 | 3472 |
2867 init_caller_stats (&stats); | 3473 init_caller_stats (&stats); |
2868 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, | 3474 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, |
2869 false); | 3475 false); |
2870 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, | 3476 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, |
2871 known_aggs_ptrs, &size, &time, | 3477 known_aggs, &size, &time, |
2872 &base_time, &hints); | 3478 &base_time, &hints); |
2873 time -= devirt_bonus; | 3479 time -= devirt_bonus; |
2874 time -= hint_time_bonus (hints); | 3480 time -= hint_time_bonus (node, hints); |
2875 time -= removable_params_cost; | 3481 time -= removable_params_cost; |
2876 size -= stats.n_calls * removable_params_cost; | 3482 size -= stats.n_calls * removable_params_cost; |
2877 | 3483 |
2878 if (dump_file) | 3484 if (dump_file) |
2879 fprintf (dump_file, " - context independent values, size: %i, " | 3485 fprintf (dump_file, " - context independent values, size: %i, " |
2880 "time_benefit: %f\n", size, (base_time - time).to_double ()); | 3486 "time_benefit: %f\n", size, (base_time - time).to_double ()); |
2881 | 3487 |
2882 if (size <= 0 || node->local.local) | 3488 if (size <= 0 || node->local) |
2883 { | 3489 { |
2884 info->do_clone_for_all_contexts = true; | 3490 info->do_clone_for_all_contexts = true; |
2885 | 3491 |
2886 if (dump_file) | 3492 if (dump_file) |
2887 fprintf (dump_file, " Decided to specialize for all " | 3493 fprintf (dump_file, " Decided to specialize for all " |
2891 MIN ((base_time - time).to_int (), | 3497 MIN ((base_time - time).to_int (), |
2892 65536), | 3498 65536), |
2893 stats.freq_sum, stats.count_sum, | 3499 stats.freq_sum, stats.count_sum, |
2894 size)) | 3500 size)) |
2895 { | 3501 { |
2896 if (size + overall_size <= max_new_size) | 3502 if (size + overall_size <= get_max_overall_size (node)) |
2897 { | 3503 { |
2898 info->do_clone_for_all_contexts = true; | 3504 info->do_clone_for_all_contexts = true; |
2899 overall_size += size; | 3505 overall_size += size; |
2900 | 3506 |
2901 if (dump_file) | 3507 if (dump_file) |
2902 fprintf (dump_file, " Decided to specialize for all " | 3508 fprintf (dump_file, " Decided to specialize for all " |
2903 "known contexts, growth deemed beneficial.\n"); | 3509 "known contexts, growth deemed beneficial.\n"); |
2904 } | 3510 } |
2905 else if (dump_file && (dump_flags & TDF_DETAILS)) | 3511 else if (dump_file && (dump_flags & TDF_DETAILS)) |
2906 fprintf (dump_file, " Not cloning for all contexts because " | 3512 fprintf (dump_file, " Not cloning for all contexts because " |
2907 "max_new_size would be reached with %li.\n", | 3513 "maximum unit size would be reached with %li.\n", |
2908 size + overall_size); | 3514 size + overall_size); |
2909 } | 3515 } |
2910 else if (dump_file && (dump_flags & TDF_DETAILS)) | 3516 else if (dump_file && (dump_flags & TDF_DETAILS)) |
2911 fprintf (dump_file, " Not cloning for all contexts because " | 3517 fprintf (dump_file, " Not cloning for all contexts because " |
2912 "!good_cloning_opportunity_p.\n"); | 3518 "!good_cloning_opportunity_p.\n"); |
2913 | 3519 |
2914 } | 3520 } |
2915 | 3521 |
2916 for (i = 0; i < count; i++) | 3522 for (i = 0; i < count; i++) |
2917 { | 3523 { |
2918 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 3524 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
2919 ipcp_lattice<tree> *lat = &plats->itself; | 3525 ipcp_lattice<tree> *lat = &plats->itself; |
2920 ipcp_value<tree> *val; | 3526 ipcp_value<tree> *val; |
2921 | 3527 |
2922 if (lat->bottom | 3528 if (lat->bottom |
2923 || !lat->values | 3529 || !lat->values |
2929 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO); | 3535 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO); |
2930 known_csts[i] = val->value; | 3536 known_csts[i] = val->value; |
2931 | 3537 |
2932 int emc = estimate_move_cost (TREE_TYPE (val->value), true); | 3538 int emc = estimate_move_cost (TREE_TYPE (val->value), true); |
2933 perform_estimation_of_a_value (node, known_csts, known_contexts, | 3539 perform_estimation_of_a_value (node, known_csts, known_contexts, |
2934 known_aggs_ptrs, | 3540 known_aggs, |
2935 removable_params_cost, emc, val); | 3541 removable_params_cost, emc, val); |
2936 | 3542 |
2937 if (dump_file && (dump_flags & TDF_DETAILS)) | 3543 if (dump_file && (dump_flags & TDF_DETAILS)) |
2938 { | 3544 { |
2939 fprintf (dump_file, " - estimates for value "); | 3545 fprintf (dump_file, " - estimates for value "); |
2947 known_csts[i] = NULL_TREE; | 3553 known_csts[i] = NULL_TREE; |
2948 } | 3554 } |
2949 | 3555 |
2950 for (i = 0; i < count; i++) | 3556 for (i = 0; i < count; i++) |
2951 { | 3557 { |
2952 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 3558 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
2953 | 3559 |
2954 if (!plats->virt_call) | 3560 if (!plats->virt_call) |
2955 continue; | 3561 continue; |
2956 | 3562 |
2957 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; | 3563 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; |
2964 | 3570 |
2965 for (val = ctxlat->values; val; val = val->next) | 3571 for (val = ctxlat->values; val; val = val->next) |
2966 { | 3572 { |
2967 known_contexts[i] = val->value; | 3573 known_contexts[i] = val->value; |
2968 perform_estimation_of_a_value (node, known_csts, known_contexts, | 3574 perform_estimation_of_a_value (node, known_csts, known_contexts, |
2969 known_aggs_ptrs, | 3575 known_aggs, |
2970 removable_params_cost, 0, val); | 3576 removable_params_cost, 0, val); |
2971 | 3577 |
2972 if (dump_file && (dump_flags & TDF_DETAILS)) | 3578 if (dump_file && (dump_flags & TDF_DETAILS)) |
2973 { | 3579 { |
2974 fprintf (dump_file, " - estimates for polymorphic context "); | 3580 fprintf (dump_file, " - estimates for polymorphic context "); |
2982 known_contexts[i] = ipa_polymorphic_call_context (); | 3588 known_contexts[i] = ipa_polymorphic_call_context (); |
2983 } | 3589 } |
2984 | 3590 |
2985 for (i = 0; i < count; i++) | 3591 for (i = 0; i < count; i++) |
2986 { | 3592 { |
2987 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 3593 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
2988 struct ipa_agg_jump_function *ajf; | 3594 struct ipa_agg_value_set *agg; |
2989 struct ipcp_agg_lattice *aglat; | 3595 struct ipcp_agg_lattice *aglat; |
2990 | 3596 |
2991 if (plats->aggs_bottom || !plats->aggs) | 3597 if (plats->aggs_bottom || !plats->aggs) |
2992 continue; | 3598 continue; |
2993 | 3599 |
2994 ajf = &known_aggs[i]; | 3600 agg = &known_aggs[i]; |
2995 for (aglat = plats->aggs; aglat; aglat = aglat->next) | 3601 for (aglat = plats->aggs; aglat; aglat = aglat->next) |
2996 { | 3602 { |
2997 ipcp_value<tree> *val; | 3603 ipcp_value<tree> *val; |
2998 if (aglat->bottom || !aglat->values | 3604 if (aglat->bottom || !aglat->values |
2999 /* If the following is true, the one value is in known_aggs. */ | 3605 /* If the following is true, the one value is in known_aggs. */ |
3001 && aglat->is_single_const ())) | 3607 && aglat->is_single_const ())) |
3002 continue; | 3608 continue; |
3003 | 3609 |
3004 for (val = aglat->values; val; val = val->next) | 3610 for (val = aglat->values; val; val = val->next) |
3005 { | 3611 { |
3006 struct ipa_agg_jf_item item; | 3612 struct ipa_agg_value item; |
3007 | 3613 |
3008 item.offset = aglat->offset; | 3614 item.offset = aglat->offset; |
3009 item.value = val->value; | 3615 item.value = val->value; |
3010 vec_safe_push (ajf->items, item); | 3616 agg->items.safe_push (item); |
3011 | 3617 |
3012 perform_estimation_of_a_value (node, known_csts, known_contexts, | 3618 perform_estimation_of_a_value (node, known_csts, known_contexts, |
3013 known_aggs_ptrs, | 3619 known_aggs, |
3014 removable_params_cost, 0, val); | 3620 removable_params_cost, 0, val); |
3015 | 3621 |
3016 if (dump_file && (dump_flags & TDF_DETAILS)) | 3622 if (dump_file && (dump_flags & TDF_DETAILS)) |
3017 { | 3623 { |
3018 fprintf (dump_file, " - estimates for value "); | 3624 fprintf (dump_file, " - estimates for value "); |
3024 plats->aggs_by_ref ? "ref " : "", | 3630 plats->aggs_by_ref ? "ref " : "", |
3025 aglat->offset, | 3631 aglat->offset, |
3026 val->local_time_benefit, val->local_size_cost); | 3632 val->local_time_benefit, val->local_size_cost); |
3027 } | 3633 } |
3028 | 3634 |
3029 ajf->items->pop (); | 3635 agg->items.pop (); |
3030 } | 3636 } |
3031 } | 3637 } |
3032 } | 3638 } |
3033 | |
3034 for (i = 0; i < count; i++) | |
3035 vec_free (known_aggs[i].items); | |
3036 | 3639 |
3037 known_csts.release (); | 3640 known_csts.release (); |
3038 known_contexts.release (); | 3641 known_contexts.release (); |
3039 known_aggs.release (); | 3642 ipa_release_agg_values (known_aggs); |
3040 known_aggs_ptrs.release (); | |
3041 } | 3643 } |
3042 | 3644 |
3043 | 3645 |
3044 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the | 3646 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the |
3045 topological sort of values. */ | 3647 topological sort of values. */ |
3099 they are not there yet. */ | 3701 they are not there yet. */ |
3100 | 3702 |
3101 static void | 3703 static void |
3102 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo) | 3704 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo) |
3103 { | 3705 { |
3104 struct ipa_node_params *info = IPA_NODE_REF (node); | 3706 class ipa_node_params *info = IPA_NODE_REF (node); |
3105 int i, count = ipa_get_param_count (info); | 3707 int i, count = ipa_get_param_count (info); |
3106 | 3708 |
3107 for (i = 0; i < count; i++) | 3709 for (i = 0; i < count; i++) |
3108 { | 3710 { |
3109 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 3711 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
3110 ipcp_lattice<tree> *lat = &plats->itself; | 3712 ipcp_lattice<tree> *lat = &plats->itself; |
3111 struct ipcp_agg_lattice *aglat; | 3713 struct ipcp_agg_lattice *aglat; |
3112 | 3714 |
3113 if (!lat->bottom) | 3715 if (!lat->bottom) |
3114 { | 3716 { |
3139 /* One pass of constants propagation along the call graph edges, from callers | 3741 /* One pass of constants propagation along the call graph edges, from callers |
3140 to callees (requires topological ordering in TOPO), iterate over strongly | 3742 to callees (requires topological ordering in TOPO), iterate over strongly |
3141 connected components. */ | 3743 connected components. */ |
3142 | 3744 |
3143 static void | 3745 static void |
3144 propagate_constants_topo (struct ipa_topo_info *topo) | 3746 propagate_constants_topo (class ipa_topo_info *topo) |
3145 { | 3747 { |
3146 int i; | 3748 int i; |
3147 | 3749 |
3148 for (i = topo->nnodes - 1; i >= 0; i--) | 3750 for (i = topo->nnodes - 1; i >= 0; i--) |
3149 { | 3751 { |
3153 | 3755 |
3154 /* First, iteratively propagate within the strongly connected component | 3756 /* First, iteratively propagate within the strongly connected component |
3155 until all lattices stabilize. */ | 3757 until all lattices stabilize. */ |
3156 FOR_EACH_VEC_ELT (cycle_nodes, j, v) | 3758 FOR_EACH_VEC_ELT (cycle_nodes, j, v) |
3157 if (v->has_gimple_body_p ()) | 3759 if (v->has_gimple_body_p ()) |
3158 push_node_to_stack (topo, v); | 3760 { |
3761 if (opt_for_fn (v->decl, flag_ipa_cp) | |
3762 && opt_for_fn (v->decl, optimize)) | |
3763 push_node_to_stack (topo, v); | |
3764 /* When V is not optimized, we can not push it to stack, but | |
3765 still we need to set all its callees lattices to bottom. */ | |
3766 else | |
3767 { | |
3768 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) | |
3769 propagate_constants_across_call (cs); | |
3770 } | |
3771 } | |
3159 | 3772 |
3160 v = pop_node_from_stack (topo); | 3773 v = pop_node_from_stack (topo); |
3161 while (v) | 3774 while (v) |
3162 { | 3775 { |
3163 struct cgraph_edge *cs; | 3776 struct cgraph_edge *cs; |
3777 class ipa_node_params *info = NULL; | |
3778 bool self_scc = true; | |
3164 | 3779 |
3165 for (cs = v->callees; cs; cs = cs->next_callee) | 3780 for (cs = v->callees; cs; cs = cs->next_callee) |
3166 if (ipa_edge_within_scc (cs)) | 3781 if (ipa_edge_within_scc (cs)) |
3167 { | 3782 { |
3168 IPA_NODE_REF (v)->node_within_scc = true; | 3783 cgraph_node *callee = cs->callee->function_symbol (); |
3784 | |
3785 if (v != callee) | |
3786 self_scc = false; | |
3787 | |
3788 if (!info) | |
3789 { | |
3790 info = IPA_NODE_REF (v); | |
3791 info->node_within_scc = true; | |
3792 } | |
3793 | |
3169 if (propagate_constants_across_call (cs)) | 3794 if (propagate_constants_across_call (cs)) |
3170 push_node_to_stack (topo, cs->callee->function_symbol ()); | 3795 push_node_to_stack (topo, callee); |
3171 } | 3796 } |
3797 | |
3798 if (info) | |
3799 info->node_is_self_scc = self_scc; | |
3800 | |
3172 v = pop_node_from_stack (topo); | 3801 v = pop_node_from_stack (topo); |
3173 } | 3802 } |
3174 | 3803 |
3175 /* Afterwards, propagate along edges leading out of the SCC, calculates | 3804 /* Afterwards, propagate along edges leading out of the SCC, calculates |
3176 the local effects of the discovered constants and all valid values to | 3805 the local effects of the discovered constants and all valid values to |
3177 their topological sort. */ | 3806 their topological sort. */ |
3178 FOR_EACH_VEC_ELT (cycle_nodes, j, v) | 3807 FOR_EACH_VEC_ELT (cycle_nodes, j, v) |
3179 if (v->has_gimple_body_p ()) | 3808 if (v->has_gimple_body_p () |
3809 && opt_for_fn (v->decl, flag_ipa_cp) | |
3810 && opt_for_fn (v->decl, optimize)) | |
3180 { | 3811 { |
3181 struct cgraph_edge *cs; | 3812 struct cgraph_edge *cs; |
3182 | 3813 |
3183 estimate_local_effects (v); | 3814 estimate_local_effects (v); |
3184 add_all_node_vals_to_toposort (v, topo); | 3815 add_all_node_vals_to_toposort (v, topo); |
3242 | 3873 |
3243 /* Propagate constants, polymorphic contexts and their effects from the | 3874 /* Propagate constants, polymorphic contexts and their effects from the |
3244 summaries interprocedurally. */ | 3875 summaries interprocedurally. */ |
3245 | 3876 |
3246 static void | 3877 static void |
3247 ipcp_propagate_stage (struct ipa_topo_info *topo) | 3878 ipcp_propagate_stage (class ipa_topo_info *topo) |
3248 { | 3879 { |
3249 struct cgraph_node *node; | 3880 struct cgraph_node *node; |
3250 | 3881 |
3251 if (dump_file) | 3882 if (dump_file) |
3252 fprintf (dump_file, "\n Propagating constants:\n\n"); | 3883 fprintf (dump_file, "\n Propagating constants:\n\n"); |
3253 | 3884 |
3254 max_count = profile_count::uninitialized (); | 3885 max_count = profile_count::uninitialized (); |
3255 | 3886 |
3256 FOR_EACH_DEFINED_FUNCTION (node) | 3887 FOR_EACH_DEFINED_FUNCTION (node) |
3257 { | 3888 { |
3258 struct ipa_node_params *info = IPA_NODE_REF (node); | 3889 if (node->has_gimple_body_p () |
3259 | 3890 && opt_for_fn (node->decl, flag_ipa_cp) |
3260 determine_versionability (node, info); | 3891 && opt_for_fn (node->decl, optimize)) |
3261 if (node->has_gimple_body_p ()) | |
3262 { | 3892 { |
3263 info->lattices = XCNEWVEC (struct ipcp_param_lattices, | 3893 class ipa_node_params *info = IPA_NODE_REF (node); |
3894 determine_versionability (node, info); | |
3895 info->lattices = XCNEWVEC (class ipcp_param_lattices, | |
3264 ipa_get_param_count (info)); | 3896 ipa_get_param_count (info)); |
3265 initialize_node_lattices (node); | 3897 initialize_node_lattices (node); |
3266 } | 3898 } |
3267 ipa_fn_summary *s = ipa_fn_summaries->get (node); | 3899 ipa_size_summary *s = ipa_size_summaries->get (node); |
3268 if (node->definition && !node->alias && s != NULL) | 3900 if (node->definition && !node->alias && s != NULL) |
3269 overall_size += s->self_size; | 3901 overall_size += s->self_size; |
3270 max_count = max_count.max (node->count.ipa ()); | 3902 max_count = max_count.max (node->count.ipa ()); |
3271 } | 3903 } |
3272 | 3904 |
3273 max_new_size = overall_size; | 3905 orig_overall_size = overall_size; |
3274 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS)) | |
3275 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS); | |
3276 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1; | |
3277 | 3906 |
3278 if (dump_file) | 3907 if (dump_file) |
3279 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n", | 3908 fprintf (dump_file, "\noverall_size: %li\n", overall_size); |
3280 overall_size, max_new_size); | |
3281 | 3909 |
3282 propagate_constants_topo (topo); | 3910 propagate_constants_topo (topo); |
3283 if (flag_checking) | 3911 if (flag_checking) |
3284 ipcp_verify_propagated_values (); | 3912 ipcp_verify_propagated_values (); |
3285 topo->constants.propagate_effects (); | 3913 topo->constants.propagate_effects (); |
3322 speculative); | 3950 speculative); |
3323 found = true; | 3951 found = true; |
3324 | 3952 |
3325 if (cs && !agg_contents && !polymorphic) | 3953 if (cs && !agg_contents && !polymorphic) |
3326 { | 3954 { |
3327 struct ipa_node_params *info = IPA_NODE_REF (node); | 3955 class ipa_node_params *info = IPA_NODE_REF (node); |
3328 int c = ipa_get_controlled_uses (info, param_index); | 3956 int c = ipa_get_controlled_uses (info, param_index); |
3329 if (c != IPA_UNDESCRIBED_USE) | 3957 if (c != IPA_UNDESCRIBED_USE) |
3330 { | 3958 { |
3331 struct ipa_ref *to_del; | 3959 struct ipa_ref *to_del; |
3332 | 3960 |
3355 class edge_clone_summary; | 3983 class edge_clone_summary; |
3356 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL; | 3984 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL; |
3357 | 3985 |
3358 /* Edge clone summary. */ | 3986 /* Edge clone summary. */ |
3359 | 3987 |
3360 struct edge_clone_summary | 3988 class edge_clone_summary |
3361 { | 3989 { |
3990 public: | |
3362 /* Default constructor. */ | 3991 /* Default constructor. */ |
3363 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {} | 3992 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {} |
3364 | 3993 |
3365 /* Default destructor. */ | 3994 /* Default destructor. */ |
3366 ~edge_clone_summary () | 3995 ~edge_clone_summary () |
3402 dst_data->prev_clone = src_edge; | 4031 dst_data->prev_clone = src_edge; |
3403 dst_data->next_clone = src_data->next_clone; | 4032 dst_data->next_clone = src_data->next_clone; |
3404 src_data->next_clone = dst_edge; | 4033 src_data->next_clone = dst_edge; |
3405 } | 4034 } |
3406 | 4035 |
3407 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a | |
3408 parameter with the given INDEX. */ | |
3409 | |
3410 static tree | |
3411 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, | |
3412 int index) | |
3413 { | |
3414 struct ipa_agg_replacement_value *aggval; | |
3415 | |
3416 aggval = ipa_get_agg_replacements_for_node (node); | |
3417 while (aggval) | |
3418 { | |
3419 if (aggval->offset == offset | |
3420 && aggval->index == index) | |
3421 return aggval->value; | |
3422 aggval = aggval->next; | |
3423 } | |
3424 return NULL_TREE; | |
3425 } | |
3426 | |
3427 /* Return true is NODE is DEST or its clone for all contexts. */ | 4036 /* Return true is NODE is DEST or its clone for all contexts. */ |
3428 | 4037 |
3429 static bool | 4038 static bool |
3430 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest) | 4039 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest) |
3431 { | 4040 { |
3432 if (node == dest) | 4041 if (node == dest) |
3433 return true; | 4042 return true; |
3434 | 4043 |
3435 struct ipa_node_params *info = IPA_NODE_REF (node); | 4044 class ipa_node_params *info = IPA_NODE_REF (node); |
3436 return info->is_all_contexts_clone && info->ipcp_orig_node == dest; | 4045 return info->is_all_contexts_clone && info->ipcp_orig_node == dest; |
3437 } | 4046 } |
3438 | 4047 |
3439 /* Return true if edge CS does bring about the value described by SRC to | 4048 /* Return true if edge CS does bring about the value described by SRC to |
3440 DEST_VAL of node DEST or its clone for all contexts. */ | 4049 DEST_VAL of node DEST or its clone for all contexts. */ |
3441 | 4050 |
3442 static bool | 4051 static bool |
3443 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src, | 4052 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src, |
3444 cgraph_node *dest, ipcp_value<tree> *dest_val) | 4053 cgraph_node *dest, ipcp_value<tree> *dest_val) |
3445 { | 4054 { |
3446 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 4055 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
3447 enum availability availability; | 4056 enum availability availability; |
3448 cgraph_node *real_dest = cs->callee->function_symbol (&availability); | 4057 cgraph_node *real_dest = cs->callee->function_symbol (&availability); |
3449 | 4058 |
3450 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) | 4059 if (availability <= AVAIL_INTERPOSABLE |
3451 || availability <= AVAIL_INTERPOSABLE | 4060 || !same_node_or_its_all_contexts_clone_p (real_dest, dest) |
3452 || caller_info->node_dead) | 4061 || caller_info->node_dead) |
3453 return false; | 4062 return false; |
3454 | 4063 |
3455 if (!src->val) | 4064 if (!src->val) |
3456 return true; | 4065 return true; |
3472 way. */ | 4081 way. */ |
3473 if (src->val == dest_val) | 4082 if (src->val == dest_val) |
3474 return true; | 4083 return true; |
3475 | 4084 |
3476 struct ipcp_agg_lattice *aglat; | 4085 struct ipcp_agg_lattice *aglat; |
3477 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, | 4086 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, |
3478 src->index); | 4087 src->index); |
3479 if (src->offset == -1) | 4088 if (src->offset == -1) |
3480 return (plats->itself.is_single_const () | 4089 return (plats->itself.is_single_const () |
3481 && values_equal_for_ipcp_p (src->val->value, | 4090 && values_equal_for_ipcp_p (src->val->value, |
3482 plats->itself.values->value)); | 4091 plats->itself.values->value)); |
3501 cgraph_edge_brings_value_p (cgraph_edge *cs, | 4110 cgraph_edge_brings_value_p (cgraph_edge *cs, |
3502 ipcp_value_source<ipa_polymorphic_call_context> *src, | 4111 ipcp_value_source<ipa_polymorphic_call_context> *src, |
3503 cgraph_node *dest, | 4112 cgraph_node *dest, |
3504 ipcp_value<ipa_polymorphic_call_context> *) | 4113 ipcp_value<ipa_polymorphic_call_context> *) |
3505 { | 4114 { |
3506 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 4115 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
3507 cgraph_node *real_dest = cs->callee->function_symbol (); | 4116 enum availability avail; |
3508 | 4117 cgraph_node *real_dest = cs->callee->function_symbol (&avail); |
3509 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) | 4118 |
4119 if (avail <= AVAIL_INTERPOSABLE | |
4120 || !same_node_or_its_all_contexts_clone_p (real_dest, dest) | |
3510 || caller_info->node_dead) | 4121 || caller_info->node_dead) |
3511 return false; | 4122 return false; |
3512 if (!src->val) | 4123 if (!src->val) |
3513 return true; | 4124 return true; |
3514 | 4125 |
3515 if (caller_info->ipcp_orig_node) | 4126 if (caller_info->ipcp_orig_node) |
3516 return (caller_info->known_contexts.length () > (unsigned) src->index) | 4127 return (caller_info->known_contexts.length () > (unsigned) src->index) |
3517 && values_equal_for_ipcp_p (src->val->value, | 4128 && values_equal_for_ipcp_p (src->val->value, |
3518 caller_info->known_contexts[src->index]); | 4129 caller_info->known_contexts[src->index]); |
3519 | 4130 |
3520 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, | 4131 class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, |
3521 src->index); | 4132 src->index); |
3522 return plats->ctxlat.is_single_const () | 4133 return plats->ctxlat.is_single_const () |
3523 && values_equal_for_ipcp_p (src->val->value, | 4134 && values_equal_for_ipcp_p (src->val->value, |
3524 plats->ctxlat.values->value); | 4135 plats->ctxlat.values->value); |
3525 } | 4136 } |
3575 return false; | 4186 return false; |
3576 | 4187 |
3577 *freq_sum = freq; | 4188 *freq_sum = freq; |
3578 *count_sum = cnt; | 4189 *count_sum = cnt; |
3579 *caller_count = count; | 4190 *caller_count = count; |
4191 | |
4192 if (!hot && IPA_NODE_REF (dest)->node_within_scc) | |
4193 { | |
4194 struct cgraph_edge *cs; | |
4195 | |
4196 /* Cold non-SCC source edge could trigger hot recursive execution of | |
4197 function. Consider the case as hot and rely on following cost model | |
4198 computation to further select right one. */ | |
4199 for (cs = dest->callers; cs; cs = cs->next_caller) | |
4200 if (cs->caller == dest && cs->maybe_hot_p ()) | |
4201 return true; | |
4202 } | |
4203 | |
3580 return hot; | 4204 return hot; |
4205 } | |
4206 | |
4207 /* Given a NODE, and a set of its CALLERS, try to adjust order of the callers | |
4208 to let a non-self-recursive caller be the first element. Thus, we can | |
4209 simplify intersecting operations on values that arrive from all of these | |
4210 callers, especially when there exists self-recursive call. Return true if | |
4211 this kind of adjustment is possible. */ | |
4212 | |
4213 static bool | |
4214 adjust_callers_for_value_intersection (vec<cgraph_edge *> callers, | |
4215 cgraph_node *node) | |
4216 { | |
4217 for (unsigned i = 0; i < callers.length (); i++) | |
4218 { | |
4219 cgraph_edge *cs = callers[i]; | |
4220 | |
4221 if (cs->caller != node) | |
4222 { | |
4223 if (i > 0) | |
4224 { | |
4225 callers[i] = callers[0]; | |
4226 callers[0] = cs; | |
4227 } | |
4228 return true; | |
4229 } | |
4230 } | |
4231 return false; | |
3581 } | 4232 } |
3582 | 4233 |
3583 /* Return a vector of incoming edges that do bring value VAL to node DEST. It | 4234 /* Return a vector of incoming edges that do bring value VAL to node DEST. It |
3584 is assumed their number is known and equal to CALLER_COUNT. */ | 4235 is assumed their number is known and equal to CALLER_COUNT. */ |
3585 | 4236 |
3601 ret.quick_push (cs); | 4252 ret.quick_push (cs); |
3602 cs = get_next_cgraph_edge_clone (cs); | 4253 cs = get_next_cgraph_edge_clone (cs); |
3603 } | 4254 } |
3604 } | 4255 } |
3605 | 4256 |
4257 if (caller_count > 1) | |
4258 adjust_callers_for_value_intersection (ret, dest); | |
4259 | |
3606 return ret; | 4260 return ret; |
3607 } | 4261 } |
3608 | 4262 |
3609 /* Construct a replacement map for a know VALUE for a formal parameter PARAM. | 4263 /* Construct a replacement map for a know VALUE for a formal parameter PARAM. |
3610 Return it or NULL if for some reason it cannot be created. */ | 4264 Return it or NULL if for some reason it cannot be created. */ |
3611 | 4265 |
3612 static struct ipa_replace_map * | 4266 static struct ipa_replace_map * |
3613 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num) | 4267 get_replacement_map (class ipa_node_params *info, tree value, int parm_num) |
3614 { | 4268 { |
3615 struct ipa_replace_map *replace_map; | 4269 struct ipa_replace_map *replace_map; |
3616 | |
3617 | 4270 |
3618 replace_map = ggc_alloc<ipa_replace_map> (); | 4271 replace_map = ggc_alloc<ipa_replace_map> (); |
3619 if (dump_file) | 4272 if (dump_file) |
3620 { | 4273 { |
3621 fprintf (dump_file, " replacing "); | 4274 fprintf (dump_file, " replacing "); |
3623 | 4276 |
3624 fprintf (dump_file, " with const "); | 4277 fprintf (dump_file, " with const "); |
3625 print_generic_expr (dump_file, value); | 4278 print_generic_expr (dump_file, value); |
3626 fprintf (dump_file, "\n"); | 4279 fprintf (dump_file, "\n"); |
3627 } | 4280 } |
3628 replace_map->old_tree = NULL; | |
3629 replace_map->parm_num = parm_num; | 4281 replace_map->parm_num = parm_num; |
3630 replace_map->new_tree = value; | 4282 replace_map->new_tree = value; |
3631 replace_map->replace_p = true; | |
3632 replace_map->ref_p = false; | |
3633 | |
3634 return replace_map; | 4283 return replace_map; |
3635 } | 4284 } |
3636 | 4285 |
3637 /* Dump new profiling counts */ | 4286 /* Dump new profiling counts */ |
3638 | 4287 |
3646 new_node->count.dump (dump_file); | 4295 new_node->count.dump (dump_file); |
3647 fprintf (dump_file, "\n"); | 4296 fprintf (dump_file, "\n"); |
3648 for (cs = new_node->callees; cs; cs = cs->next_callee) | 4297 for (cs = new_node->callees; cs; cs = cs->next_callee) |
3649 { | 4298 { |
3650 fprintf (dump_file, " edge to %s has count ", | 4299 fprintf (dump_file, " edge to %s has count ", |
3651 cs->callee->name ()); | 4300 cs->callee->dump_name ()); |
3652 cs->count.dump (dump_file); | 4301 cs->count.dump (dump_file); |
3653 fprintf (dump_file, "\n"); | 4302 fprintf (dump_file, "\n"); |
3654 } | 4303 } |
3655 | 4304 |
3656 fprintf (dump_file, " setting count of the original node to "); | 4305 fprintf (dump_file, " setting count of the original node to "); |
3657 orig_node->count.dump (dump_file); | 4306 orig_node->count.dump (dump_file); |
3658 fprintf (dump_file, "\n"); | 4307 fprintf (dump_file, "\n"); |
3659 for (cs = orig_node->callees; cs; cs = cs->next_callee) | 4308 for (cs = orig_node->callees; cs; cs = cs->next_callee) |
3660 { | 4309 { |
3661 fprintf (dump_file, " edge to %s is left with ", | 4310 fprintf (dump_file, " edge to %s is left with ", |
3662 cs->callee->name ()); | 4311 cs->callee->dump_name ()); |
3663 cs->count.dump (dump_file); | 4312 cs->count.dump (dump_file); |
3664 fprintf (dump_file, "\n"); | 4313 fprintf (dump_file, "\n"); |
3665 } | 4314 } |
3666 } | 4315 } |
3667 | 4316 |
3674 { | 4323 { |
3675 struct cgraph_edge *cs; | 4324 struct cgraph_edge *cs; |
3676 struct caller_statistics stats; | 4325 struct caller_statistics stats; |
3677 profile_count new_sum, orig_sum; | 4326 profile_count new_sum, orig_sum; |
3678 profile_count remainder, orig_node_count = orig_node->count; | 4327 profile_count remainder, orig_node_count = orig_node->count; |
4328 profile_count orig_new_node_count = new_node->count; | |
3679 | 4329 |
3680 if (!(orig_node_count.ipa () > profile_count::zero ())) | 4330 if (!(orig_node_count.ipa () > profile_count::zero ())) |
3681 return; | 4331 return; |
3682 | 4332 |
3683 init_caller_stats (&stats); | 4333 init_caller_stats (&stats); |
3710 } | 4360 } |
3711 } | 4361 } |
3712 | 4362 |
3713 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa () | 4363 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa () |
3714 - new_sum.ipa ()); | 4364 - new_sum.ipa ()); |
4365 | |
4366 /* With partial train run we do not want to assume that original's | |
4367 count is zero whenever we redurect all executed edges to clone. | |
4368 Simply drop profile to local one in this case. */ | |
4369 if (remainder.ipa_p () && !remainder.ipa ().nonzero_p () | |
4370 && orig_node->count.ipa_p () && orig_node->count.ipa ().nonzero_p () | |
4371 && flag_profile_partial_training) | |
4372 remainder = remainder.guessed_local (); | |
4373 | |
3715 new_sum = orig_node_count.combine_with_ipa_count (new_sum); | 4374 new_sum = orig_node_count.combine_with_ipa_count (new_sum); |
4375 new_node->count = new_sum; | |
3716 orig_node->count = remainder; | 4376 orig_node->count = remainder; |
3717 | 4377 |
4378 profile_count::adjust_for_ipa_scaling (&new_sum, &orig_new_node_count); | |
3718 for (cs = new_node->callees; cs; cs = cs->next_callee) | 4379 for (cs = new_node->callees; cs; cs = cs->next_callee) |
3719 cs->count = cs->count.apply_scale (new_sum, orig_node_count); | 4380 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count); |
3720 | 4381 for (cs = new_node->indirect_calls; cs; cs = cs->next_callee) |
4382 cs->count = cs->count.apply_scale (new_sum, orig_new_node_count); | |
4383 | |
4384 profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count); | |
3721 for (cs = orig_node->callees; cs; cs = cs->next_callee) | 4385 for (cs = orig_node->callees; cs; cs = cs->next_callee) |
4386 cs->count = cs->count.apply_scale (remainder, orig_node_count); | |
4387 for (cs = orig_node->indirect_calls; cs; cs = cs->next_callee) | |
3722 cs->count = cs->count.apply_scale (remainder, orig_node_count); | 4388 cs->count = cs->count.apply_scale (remainder, orig_node_count); |
3723 | 4389 |
3724 if (dump_file) | 4390 if (dump_file) |
3725 dump_profile_updates (orig_node, new_node); | 4391 dump_profile_updates (orig_node, new_node); |
3726 } | 4392 } |
3762 cs->count -= dec; | 4428 cs->count -= dec; |
3763 } | 4429 } |
3764 | 4430 |
3765 if (dump_file) | 4431 if (dump_file) |
3766 dump_profile_updates (orig_node, new_node); | 4432 dump_profile_updates (orig_node, new_node); |
4433 } | |
4434 | |
4435 /* Return true if we would like to remove a parameter from NODE when cloning it | |
4436 with KNOWN_CSTS scalar constants. */ | |
4437 | |
4438 static bool | |
4439 want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts) | |
4440 { | |
4441 auto_vec<bool, 16> surviving; | |
4442 bool filled_vec = false; | |
4443 ipa_node_params *info = IPA_NODE_REF (node); | |
4444 int i, count = ipa_get_param_count (info); | |
4445 | |
4446 for (i = 0; i < count; i++) | |
4447 { | |
4448 if (!known_csts[i] && ipa_is_param_used (info, i)) | |
4449 continue; | |
4450 | |
4451 if (!filled_vec) | |
4452 { | |
4453 if (!node->clone.param_adjustments) | |
4454 return true; | |
4455 node->clone.param_adjustments->get_surviving_params (&surviving); | |
4456 filled_vec = true; | |
4457 } | |
4458 if (surviving.length() < (unsigned) i && surviving[i]) | |
4459 return true; | |
4460 } | |
4461 return false; | |
3767 } | 4462 } |
3768 | 4463 |
3769 /* Create a specialized version of NODE with known constants in KNOWN_CSTS, | 4464 /* Create a specialized version of NODE with known constants in KNOWN_CSTS, |
3770 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and | 4465 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and |
3771 redirect all edges in CALLERS to it. */ | 4466 redirect all edges in CALLERS to it. */ |
3775 vec<tree> known_csts, | 4470 vec<tree> known_csts, |
3776 vec<ipa_polymorphic_call_context> known_contexts, | 4471 vec<ipa_polymorphic_call_context> known_contexts, |
3777 struct ipa_agg_replacement_value *aggvals, | 4472 struct ipa_agg_replacement_value *aggvals, |
3778 vec<cgraph_edge *> callers) | 4473 vec<cgraph_edge *> callers) |
3779 { | 4474 { |
3780 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node); | 4475 class ipa_node_params *new_info, *info = IPA_NODE_REF (node); |
3781 vec<ipa_replace_map *, va_gc> *replace_trees = NULL; | 4476 vec<ipa_replace_map *, va_gc> *replace_trees = NULL; |
4477 vec<ipa_adjusted_param, va_gc> *new_params = NULL; | |
3782 struct ipa_agg_replacement_value *av; | 4478 struct ipa_agg_replacement_value *av; |
3783 struct cgraph_node *new_node; | 4479 struct cgraph_node *new_node; |
3784 int i, count = ipa_get_param_count (info); | 4480 int i, count = ipa_get_param_count (info); |
3785 bitmap args_to_skip; | 4481 ipa_param_adjustments *old_adjustments = node->clone.param_adjustments; |
3786 | 4482 ipa_param_adjustments *new_adjustments; |
3787 gcc_assert (!info->ipcp_orig_node); | 4483 gcc_assert (!info->ipcp_orig_node); |
3788 | 4484 gcc_assert (node->can_change_signature |
3789 if (node->local.can_change_signature) | 4485 || !old_adjustments); |
3790 { | 4486 |
3791 args_to_skip = BITMAP_GGC_ALLOC (); | 4487 if (old_adjustments) |
4488 { | |
4489 /* At the moment all IPA optimizations should use the number of | |
4490 parameters of the prevailing decl as the m_always_copy_start. | |
4491 Handling any other value would complicate the code below, so for the | |
4492 time bing let's only assert it is so. */ | |
4493 gcc_assert (old_adjustments->m_always_copy_start == count | |
4494 || old_adjustments->m_always_copy_start < 0); | |
4495 int old_adj_count = vec_safe_length (old_adjustments->m_adj_params); | |
4496 for (i = 0; i < old_adj_count; i++) | |
4497 { | |
4498 ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i]; | |
4499 if (!node->can_change_signature | |
4500 || old_adj->op != IPA_PARAM_OP_COPY | |
4501 || (!known_csts[old_adj->base_index] | |
4502 && ipa_is_param_used (info, old_adj->base_index))) | |
4503 { | |
4504 ipa_adjusted_param new_adj = *old_adj; | |
4505 | |
4506 new_adj.prev_clone_adjustment = true; | |
4507 new_adj.prev_clone_index = i; | |
4508 vec_safe_push (new_params, new_adj); | |
4509 } | |
4510 } | |
4511 bool skip_return = old_adjustments->m_skip_return; | |
4512 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ()) | |
4513 ipa_param_adjustments (new_params, count, | |
4514 skip_return)); | |
4515 } | |
4516 else if (node->can_change_signature | |
4517 && want_remove_some_param_p (node, known_csts)) | |
4518 { | |
4519 ipa_adjusted_param adj; | |
4520 memset (&adj, 0, sizeof (adj)); | |
4521 adj.op = IPA_PARAM_OP_COPY; | |
3792 for (i = 0; i < count; i++) | 4522 for (i = 0; i < count; i++) |
3793 { | 4523 if (!known_csts[i] && ipa_is_param_used (info, i)) |
3794 tree t = known_csts[i]; | 4524 { |
3795 | 4525 adj.base_index = i; |
3796 if (t || !ipa_is_param_used (info, i)) | 4526 adj.prev_clone_index = i; |
3797 bitmap_set_bit (args_to_skip, i); | 4527 vec_safe_push (new_params, adj); |
3798 } | 4528 } |
4529 new_adjustments = (new (ggc_alloc <ipa_param_adjustments> ()) | |
4530 ipa_param_adjustments (new_params, count, false)); | |
3799 } | 4531 } |
3800 else | 4532 else |
3801 { | 4533 new_adjustments = NULL; |
3802 args_to_skip = NULL; | 4534 |
3803 if (dump_file && (dump_flags & TDF_DETAILS)) | 4535 replace_trees = vec_safe_copy (node->clone.tree_map); |
3804 fprintf (dump_file, " cannot change function signature\n"); | |
3805 } | |
3806 | |
3807 for (i = 0; i < count; i++) | 4536 for (i = 0; i < count; i++) |
3808 { | 4537 { |
3809 tree t = known_csts[i]; | 4538 tree t = known_csts[i]; |
3810 if (t) | 4539 if (t) |
3811 { | 4540 { |
3826 self_recursive_calls.safe_push (cs); | 4555 self_recursive_calls.safe_push (cs); |
3827 callers.unordered_remove (i); | 4556 callers.unordered_remove (i); |
3828 } | 4557 } |
3829 } | 4558 } |
3830 | 4559 |
4560 unsigned &suffix_counter = clone_num_suffixes->get_or_insert ( | |
4561 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME ( | |
4562 node->decl))); | |
3831 new_node = node->create_virtual_clone (callers, replace_trees, | 4563 new_node = node->create_virtual_clone (callers, replace_trees, |
3832 args_to_skip, "constprop"); | 4564 new_adjustments, "constprop", |
4565 suffix_counter); | |
4566 suffix_counter++; | |
3833 | 4567 |
3834 bool have_self_recursive_calls = !self_recursive_calls.is_empty (); | 4568 bool have_self_recursive_calls = !self_recursive_calls.is_empty (); |
3835 for (unsigned j = 0; j < self_recursive_calls.length (); j++) | 4569 for (unsigned j = 0; j < self_recursive_calls.length (); j++) |
3836 { | 4570 { |
3837 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]); | 4571 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]); |
3871 } | 4605 } |
3872 ipa_check_create_node_params (); | 4606 ipa_check_create_node_params (); |
3873 update_profiling_info (node, new_node); | 4607 update_profiling_info (node, new_node); |
3874 new_info = IPA_NODE_REF (new_node); | 4608 new_info = IPA_NODE_REF (new_node); |
3875 new_info->ipcp_orig_node = node; | 4609 new_info->ipcp_orig_node = node; |
4610 new_node->ipcp_clone = true; | |
3876 new_info->known_csts = known_csts; | 4611 new_info->known_csts = known_csts; |
3877 new_info->known_contexts = known_contexts; | 4612 new_info->known_contexts = known_contexts; |
3878 | 4613 |
3879 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals); | 4614 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals); |
3880 | 4615 |
3881 callers.release (); | 4616 callers.release (); |
3882 return new_node; | 4617 return new_node; |
3883 } | 4618 } |
3884 | 4619 |
3885 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a | 4620 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a |
3886 simple no-operation pass-through function to itself. */ | 4621 pass-through function to itself. When SIMPLE is true, further check if |
4622 JFUNC is a simple no-operation pass-through. */ | |
3887 | 4623 |
3888 static bool | 4624 static bool |
3889 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i) | 4625 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i, |
4626 bool simple = true) | |
3890 { | 4627 { |
3891 enum availability availability; | 4628 enum availability availability; |
3892 if (cs->caller == cs->callee->function_symbol (&availability) | 4629 if (cs->caller == cs->callee->function_symbol (&availability) |
3893 && availability > AVAIL_INTERPOSABLE | 4630 && availability > AVAIL_INTERPOSABLE |
3894 && jfunc->type == IPA_JF_PASS_THROUGH | 4631 && jfunc->type == IPA_JF_PASS_THROUGH |
3895 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR | 4632 && (!simple || ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) |
3896 && ipa_get_jf_pass_through_formal_id (jfunc) == i) | 4633 && ipa_get_jf_pass_through_formal_id (jfunc) == i) |
4634 return true; | |
4635 return false; | |
4636 } | |
4637 | |
4638 /* Return true, if JFUNC, which describes a part of an aggregate represented | |
4639 or pointed to by the i-th parameter of call CS, is a pass-through function | |
4640 to itself. When SIMPLE is true, further check if JFUNC is a simple | |
4641 no-operation pass-through. */ | |
4642 | |
4643 static bool | |
4644 self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc, | |
4645 int i, bool simple = true) | |
4646 { | |
4647 enum availability availability; | |
4648 if (cs->caller == cs->callee->function_symbol (&availability) | |
4649 && availability > AVAIL_INTERPOSABLE | |
4650 && jfunc->jftype == IPA_JF_LOAD_AGG | |
4651 && jfunc->offset == jfunc->value.load_agg.offset | |
4652 && (!simple || jfunc->value.pass_through.operation == NOP_EXPR) | |
4653 && jfunc->value.pass_through.formal_id == i | |
4654 && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type)) | |
3897 return true; | 4655 return true; |
3898 return false; | 4656 return false; |
3899 } | 4657 } |
3900 | 4658 |
3901 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in | 4659 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in |
3904 static void | 4662 static void |
3905 find_more_scalar_values_for_callers_subset (struct cgraph_node *node, | 4663 find_more_scalar_values_for_callers_subset (struct cgraph_node *node, |
3906 vec<tree> known_csts, | 4664 vec<tree> known_csts, |
3907 vec<cgraph_edge *> callers) | 4665 vec<cgraph_edge *> callers) |
3908 { | 4666 { |
3909 struct ipa_node_params *info = IPA_NODE_REF (node); | 4667 class ipa_node_params *info = IPA_NODE_REF (node); |
3910 int i, count = ipa_get_param_count (info); | 4668 int i, count = ipa_get_param_count (info); |
3911 | 4669 |
3912 for (i = 0; i < count; i++) | 4670 for (i = 0; i < count; i++) |
3913 { | 4671 { |
3914 struct cgraph_edge *cs; | 4672 struct cgraph_edge *cs; |
3923 FOR_EACH_VEC_ELT (callers, j, cs) | 4681 FOR_EACH_VEC_ELT (callers, j, cs) |
3924 { | 4682 { |
3925 struct ipa_jump_func *jump_func; | 4683 struct ipa_jump_func *jump_func; |
3926 tree t; | 4684 tree t; |
3927 | 4685 |
3928 if (IPA_NODE_REF (cs->caller)->node_dead) | 4686 if (!IPA_EDGE_REF (cs) |
3929 continue; | 4687 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) |
3930 | |
3931 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) | |
3932 || (i == 0 | 4688 || (i == 0 |
3933 && call_passes_through_thunk_p (cs))) | 4689 && call_passes_through_thunk_p (cs))) |
3934 { | 4690 { |
3935 newval = NULL_TREE; | 4691 newval = NULL_TREE; |
3936 break; | 4692 break; |
3937 } | 4693 } |
3938 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | 4694 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); |
3939 if (self_recursive_pass_through_p (cs, jump_func, i)) | 4695 |
3940 continue; | 4696 /* Besides simple pass-through jump function, arithmetic jump |
3941 | 4697 function could also introduce argument-direct-pass-through for |
3942 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func, type); | 4698 self-feeding recursive call. For example, |
4699 | |
4700 fn (int i) | |
4701 { | |
4702 fn (i & 1); | |
4703 } | |
4704 | |
4705 Given that i is 0, recursive propagation via (i & 1) also gets | |
4706 0. */ | |
4707 if (self_recursive_pass_through_p (cs, jump_func, i, false)) | |
4708 { | |
4709 gcc_assert (newval); | |
4710 t = ipa_get_jf_arith_result ( | |
4711 ipa_get_jf_pass_through_operation (jump_func), | |
4712 newval, | |
4713 ipa_get_jf_pass_through_operand (jump_func), | |
4714 type); | |
4715 } | |
4716 else | |
4717 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func, | |
4718 type); | |
3943 if (!t | 4719 if (!t |
3944 || (newval | 4720 || (newval |
3945 && !values_equal_for_ipcp_p (t, newval)) | 4721 && !values_equal_for_ipcp_p (t, newval)) |
3946 || (!first && !newval)) | 4722 || (!first && !newval)) |
3947 { | 4723 { |
3995 bool first = true; | 4771 bool first = true; |
3996 int j; | 4772 int j; |
3997 | 4773 |
3998 FOR_EACH_VEC_ELT (callers, j, cs) | 4774 FOR_EACH_VEC_ELT (callers, j, cs) |
3999 { | 4775 { |
4000 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))) | 4776 if (!IPA_EDGE_REF (cs) |
4777 || i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))) | |
4001 return; | 4778 return; |
4002 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), | 4779 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), |
4003 i); | 4780 i); |
4004 ipa_polymorphic_call_context ctx; | 4781 ipa_polymorphic_call_context ctx; |
4005 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i, | 4782 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i, |
4036 } | 4813 } |
4037 | 4814 |
4038 /* Go through PLATS and create a vector of values consisting of values and | 4815 /* Go through PLATS and create a vector of values consisting of values and |
4039 offsets (minus OFFSET) of lattices that contain only a single value. */ | 4816 offsets (minus OFFSET) of lattices that contain only a single value. */ |
4040 | 4817 |
4041 static vec<ipa_agg_jf_item> | 4818 static vec<ipa_agg_value> |
4042 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) | 4819 copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset) |
4043 { | 4820 { |
4044 vec<ipa_agg_jf_item> res = vNULL; | 4821 vec<ipa_agg_value> res = vNULL; |
4045 | 4822 |
4046 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) | 4823 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) |
4047 return vNULL; | 4824 return vNULL; |
4048 | 4825 |
4049 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) | 4826 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) |
4050 if (aglat->is_single_const ()) | 4827 if (aglat->is_single_const ()) |
4051 { | 4828 { |
4052 struct ipa_agg_jf_item ti; | 4829 struct ipa_agg_value ti; |
4053 ti.offset = aglat->offset - offset; | 4830 ti.offset = aglat->offset - offset; |
4054 ti.value = aglat->values->value; | 4831 ti.value = aglat->values->value; |
4055 res.safe_push (ti); | 4832 res.safe_push (ti); |
4056 } | 4833 } |
4057 return res; | 4834 return res; |
4059 | 4836 |
4060 /* Intersect all values in INTER with single value lattices in PLATS (while | 4837 /* Intersect all values in INTER with single value lattices in PLATS (while |
4061 subtracting OFFSET). */ | 4838 subtracting OFFSET). */ |
4062 | 4839 |
4063 static void | 4840 static void |
4064 intersect_with_plats (struct ipcp_param_lattices *plats, | 4841 intersect_with_plats (class ipcp_param_lattices *plats, |
4065 vec<ipa_agg_jf_item> *inter, | 4842 vec<ipa_agg_value> *inter, |
4066 HOST_WIDE_INT offset) | 4843 HOST_WIDE_INT offset) |
4067 { | 4844 { |
4068 struct ipcp_agg_lattice *aglat; | 4845 struct ipcp_agg_lattice *aglat; |
4069 struct ipa_agg_jf_item *item; | 4846 struct ipa_agg_value *item; |
4070 int k; | 4847 int k; |
4071 | 4848 |
4072 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) | 4849 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) |
4073 { | 4850 { |
4074 inter->release (); | 4851 inter->release (); |
4085 { | 4862 { |
4086 if (aglat->offset - offset > item->offset) | 4863 if (aglat->offset - offset > item->offset) |
4087 break; | 4864 break; |
4088 if (aglat->offset - offset == item->offset) | 4865 if (aglat->offset - offset == item->offset) |
4089 { | 4866 { |
4090 gcc_checking_assert (item->value); | 4867 if (aglat->is_single_const ()) |
4091 if (aglat->is_single_const () | 4868 { |
4092 && values_equal_for_ipcp_p (item->value, | 4869 tree value = aglat->values->value; |
4093 aglat->values->value)) | 4870 |
4094 found = true; | 4871 if (values_equal_for_ipcp_p (item->value, value)) |
4872 found = true; | |
4873 } | |
4095 break; | 4874 break; |
4096 } | 4875 } |
4097 aglat = aglat->next; | 4876 aglat = aglat->next; |
4098 } | 4877 } |
4099 if (!found) | 4878 if (!found) |
4102 } | 4881 } |
4103 | 4882 |
4104 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the | 4883 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the |
4105 vector result while subtracting OFFSET from the individual value offsets. */ | 4884 vector result while subtracting OFFSET from the individual value offsets. */ |
4106 | 4885 |
4107 static vec<ipa_agg_jf_item> | 4886 static vec<ipa_agg_value> |
4108 agg_replacements_to_vector (struct cgraph_node *node, int index, | 4887 agg_replacements_to_vector (struct cgraph_node *node, int index, |
4109 HOST_WIDE_INT offset) | 4888 HOST_WIDE_INT offset) |
4110 { | 4889 { |
4111 struct ipa_agg_replacement_value *av; | 4890 struct ipa_agg_replacement_value *av; |
4112 vec<ipa_agg_jf_item> res = vNULL; | 4891 vec<ipa_agg_value> res = vNULL; |
4113 | 4892 |
4114 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next) | 4893 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next) |
4115 if (av->index == index | 4894 if (av->index == index |
4116 && (av->offset - offset) >= 0) | 4895 && (av->offset - offset) >= 0) |
4117 { | 4896 { |
4118 struct ipa_agg_jf_item item; | 4897 struct ipa_agg_value item; |
4119 gcc_checking_assert (av->value); | 4898 gcc_checking_assert (av->value); |
4120 item.offset = av->offset - offset; | 4899 item.offset = av->offset - offset; |
4121 item.value = av->value; | 4900 item.value = av->value; |
4122 res.safe_push (item); | 4901 res.safe_push (item); |
4123 } | 4902 } |
4129 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone | 4908 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone |
4130 (while subtracting OFFSET). */ | 4909 (while subtracting OFFSET). */ |
4131 | 4910 |
4132 static void | 4911 static void |
4133 intersect_with_agg_replacements (struct cgraph_node *node, int index, | 4912 intersect_with_agg_replacements (struct cgraph_node *node, int index, |
4134 vec<ipa_agg_jf_item> *inter, | 4913 vec<ipa_agg_value> *inter, |
4135 HOST_WIDE_INT offset) | 4914 HOST_WIDE_INT offset) |
4136 { | 4915 { |
4137 struct ipa_agg_replacement_value *srcvals; | 4916 struct ipa_agg_replacement_value *srcvals; |
4138 struct ipa_agg_jf_item *item; | 4917 struct ipa_agg_value *item; |
4139 int i; | 4918 int i; |
4140 | 4919 |
4141 srcvals = ipa_get_agg_replacements_for_node (node); | 4920 srcvals = ipa_get_agg_replacements_for_node (node); |
4142 if (!srcvals) | 4921 if (!srcvals) |
4143 { | 4922 { |
4170 /* Intersect values in INTER with aggregate values that come along edge CS to | 4949 /* Intersect values in INTER with aggregate values that come along edge CS to |
4171 parameter number INDEX and return it. If INTER does not actually exist yet, | 4950 parameter number INDEX and return it. If INTER does not actually exist yet, |
4172 copy all incoming values to it. If we determine we ended up with no values | 4951 copy all incoming values to it. If we determine we ended up with no values |
4173 whatsoever, return a released vector. */ | 4952 whatsoever, return a released vector. */ |
4174 | 4953 |
4175 static vec<ipa_agg_jf_item> | 4954 static vec<ipa_agg_value> |
4176 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, | 4955 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, |
4177 vec<ipa_agg_jf_item> inter) | 4956 vec<ipa_agg_value> inter) |
4178 { | 4957 { |
4179 struct ipa_jump_func *jfunc; | 4958 struct ipa_jump_func *jfunc; |
4180 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index); | 4959 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index); |
4181 if (jfunc->type == IPA_JF_PASS_THROUGH | 4960 if (jfunc->type == IPA_JF_PASS_THROUGH |
4182 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | 4961 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) |
4183 { | 4962 { |
4184 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 4963 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
4185 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | 4964 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); |
4186 | 4965 |
4187 if (caller_info->ipcp_orig_node) | 4966 if (caller_info->ipcp_orig_node) |
4188 { | 4967 { |
4189 struct cgraph_node *orig_node = caller_info->ipcp_orig_node; | 4968 struct cgraph_node *orig_node = caller_info->ipcp_orig_node; |
4190 struct ipcp_param_lattices *orig_plats; | 4969 class ipcp_param_lattices *orig_plats; |
4191 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node), | 4970 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node), |
4192 src_idx); | 4971 src_idx); |
4193 if (agg_pass_through_permissible_p (orig_plats, jfunc)) | 4972 if (agg_pass_through_permissible_p (orig_plats, jfunc)) |
4194 { | 4973 { |
4195 if (!inter.exists ()) | 4974 if (!inter.exists ()) |
4204 return vNULL; | 4983 return vNULL; |
4205 } | 4984 } |
4206 } | 4985 } |
4207 else | 4986 else |
4208 { | 4987 { |
4209 struct ipcp_param_lattices *src_plats; | 4988 class ipcp_param_lattices *src_plats; |
4210 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | 4989 src_plats = ipa_get_parm_lattices (caller_info, src_idx); |
4211 if (agg_pass_through_permissible_p (src_plats, jfunc)) | 4990 if (agg_pass_through_permissible_p (src_plats, jfunc)) |
4212 { | 4991 { |
4213 /* Currently we do not produce clobber aggregate jump | 4992 /* Currently we do not produce clobber aggregate jump |
4214 functions, adjust when we do. */ | 4993 functions, adjust when we do. */ |
4226 } | 5005 } |
4227 } | 5006 } |
4228 else if (jfunc->type == IPA_JF_ANCESTOR | 5007 else if (jfunc->type == IPA_JF_ANCESTOR |
4229 && ipa_get_jf_ancestor_agg_preserved (jfunc)) | 5008 && ipa_get_jf_ancestor_agg_preserved (jfunc)) |
4230 { | 5009 { |
4231 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 5010 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
4232 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | 5011 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); |
4233 struct ipcp_param_lattices *src_plats; | 5012 class ipcp_param_lattices *src_plats; |
4234 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc); | 5013 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc); |
4235 | 5014 |
4236 if (caller_info->ipcp_orig_node) | 5015 if (caller_info->ipcp_orig_node) |
4237 { | 5016 { |
4238 if (!inter.exists ()) | 5017 if (!inter.exists ()) |
4253 intersect_with_plats (src_plats, &inter, delta); | 5032 intersect_with_plats (src_plats, &inter, delta); |
4254 } | 5033 } |
4255 } | 5034 } |
4256 else if (jfunc->agg.items) | 5035 else if (jfunc->agg.items) |
4257 { | 5036 { |
4258 struct ipa_agg_jf_item *item; | 5037 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
5038 struct ipa_agg_value *item; | |
4259 int k; | 5039 int k; |
4260 | 5040 |
4261 if (!inter.exists ()) | 5041 if (!inter.exists ()) |
4262 for (unsigned i = 0; i < jfunc->agg.items->length (); i++) | 5042 for (unsigned i = 0; i < jfunc->agg.items->length (); i++) |
4263 inter.safe_push ((*jfunc->agg.items)[i]); | 5043 { |
5044 struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i]; | |
5045 tree value = ipa_agg_value_from_node (caller_info, cs->caller, | |
5046 agg_item); | |
5047 if (value) | |
5048 { | |
5049 struct ipa_agg_value agg_value; | |
5050 | |
5051 agg_value.value = value; | |
5052 agg_value.offset = agg_item->offset; | |
5053 inter.safe_push (agg_value); | |
5054 } | |
5055 } | |
4264 else | 5056 else |
4265 FOR_EACH_VEC_ELT (inter, k, item) | 5057 FOR_EACH_VEC_ELT (inter, k, item) |
4266 { | 5058 { |
4267 int l = 0; | 5059 int l = 0; |
4268 bool found = false; | 5060 bool found = false; |
4276 ti = &(*jfunc->agg.items)[l]; | 5068 ti = &(*jfunc->agg.items)[l]; |
4277 if (ti->offset > item->offset) | 5069 if (ti->offset > item->offset) |
4278 break; | 5070 break; |
4279 if (ti->offset == item->offset) | 5071 if (ti->offset == item->offset) |
4280 { | 5072 { |
4281 gcc_checking_assert (ti->value); | 5073 tree value; |
4282 if (values_equal_for_ipcp_p (item->value, | 5074 |
4283 ti->value)) | 5075 /* Besides simple pass-through aggregate jump function, |
5076 arithmetic aggregate jump function could also bring | |
5077 same aggregate value as parameter passed-in for | |
5078 self-feeding recursive call. For example, | |
5079 | |
5080 fn (int *i) | |
5081 { | |
5082 int j = *i & 1; | |
5083 fn (&j); | |
5084 } | |
5085 | |
5086 Given that *i is 0, recursive propagation via (*i & 1) | |
5087 also gets 0. */ | |
5088 if (self_recursive_agg_pass_through_p (cs, ti, index, | |
5089 false)) | |
5090 value = ipa_get_jf_arith_result ( | |
5091 ti->value.pass_through.operation, | |
5092 item->value, | |
5093 ti->value.pass_through.operand, | |
5094 ti->type); | |
5095 else | |
5096 value = ipa_agg_value_from_node (caller_info, | |
5097 cs->caller, ti); | |
5098 | |
5099 if (value && values_equal_for_ipcp_p (item->value, value)) | |
4284 found = true; | 5100 found = true; |
4285 break; | 5101 break; |
4286 } | 5102 } |
4287 l++; | 5103 l++; |
4288 } | 5104 } |
4291 } | 5107 } |
4292 } | 5108 } |
4293 else | 5109 else |
4294 { | 5110 { |
4295 inter.release (); | 5111 inter.release (); |
4296 return vec<ipa_agg_jf_item>(); | 5112 return vNULL; |
4297 } | 5113 } |
4298 return inter; | 5114 return inter; |
4299 } | 5115 } |
4300 | 5116 |
4301 /* Look at edges in CALLERS and collect all known aggregate values that arrive | 5117 /* Look at edges in CALLERS and collect all known aggregate values that arrive |
4303 | 5119 |
4304 static struct ipa_agg_replacement_value * | 5120 static struct ipa_agg_replacement_value * |
4305 find_aggregate_values_for_callers_subset (struct cgraph_node *node, | 5121 find_aggregate_values_for_callers_subset (struct cgraph_node *node, |
4306 vec<cgraph_edge *> callers) | 5122 vec<cgraph_edge *> callers) |
4307 { | 5123 { |
4308 struct ipa_node_params *dest_info = IPA_NODE_REF (node); | 5124 class ipa_node_params *dest_info = IPA_NODE_REF (node); |
4309 struct ipa_agg_replacement_value *res; | 5125 struct ipa_agg_replacement_value *res; |
4310 struct ipa_agg_replacement_value **tail = &res; | 5126 struct ipa_agg_replacement_value **tail = &res; |
4311 struct cgraph_edge *cs; | 5127 struct cgraph_edge *cs; |
4312 int i, j, count = ipa_get_param_count (dest_info); | 5128 int i, j, count = ipa_get_param_count (dest_info); |
4313 | 5129 |
4314 FOR_EACH_VEC_ELT (callers, j, cs) | 5130 FOR_EACH_VEC_ELT (callers, j, cs) |
4315 { | 5131 { |
5132 if (!IPA_EDGE_REF (cs)) | |
5133 { | |
5134 count = 0; | |
5135 break; | |
5136 } | |
4316 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); | 5137 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); |
4317 if (c < count) | 5138 if (c < count) |
4318 count = c; | 5139 count = c; |
4319 } | 5140 } |
4320 | 5141 |
4321 for (i = 0; i < count; i++) | 5142 for (i = 0; i < count; i++) |
4322 { | 5143 { |
4323 struct cgraph_edge *cs; | 5144 struct cgraph_edge *cs; |
4324 vec<ipa_agg_jf_item> inter = vNULL; | 5145 vec<ipa_agg_value> inter = vNULL; |
4325 struct ipa_agg_jf_item *item; | 5146 struct ipa_agg_value *item; |
4326 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); | 5147 class ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); |
4327 int j; | 5148 int j; |
4328 | 5149 |
4329 /* Among other things, the following check should deal with all by_ref | 5150 /* Among other things, the following check should deal with all by_ref |
4330 mismatches. */ | 5151 mismatches. */ |
4331 if (plats->aggs_bottom) | 5152 if (plats->aggs_bottom) |
4374 | 5195 |
4375 static bool | 5196 static bool |
4376 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, | 5197 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, |
4377 struct cgraph_node *node) | 5198 struct cgraph_node *node) |
4378 { | 5199 { |
4379 struct ipa_node_params *dest_info = IPA_NODE_REF (node); | 5200 class ipa_node_params *dest_info = IPA_NODE_REF (node); |
4380 int count = ipa_get_param_count (dest_info); | 5201 int count = ipa_get_param_count (dest_info); |
4381 struct ipa_node_params *caller_info; | 5202 class ipa_node_params *caller_info; |
4382 struct ipa_edge_args *args; | 5203 class ipa_edge_args *args; |
4383 int i; | 5204 int i; |
4384 | 5205 |
4385 caller_info = IPA_NODE_REF (cs->caller); | 5206 caller_info = IPA_NODE_REF (cs->caller); |
4386 args = IPA_EDGE_REF (cs); | 5207 args = IPA_EDGE_REF (cs); |
4387 for (i = 0; i < count; i++) | 5208 for (i = 0; i < count; i++) |
4408 specialized for. */ | 5229 specialized for. */ |
4409 static bool | 5230 static bool |
4410 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, | 5231 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, |
4411 struct cgraph_node *node) | 5232 struct cgraph_node *node) |
4412 { | 5233 { |
4413 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller); | 5234 class ipa_node_params *orig_node_info; |
4414 struct ipa_node_params *orig_node_info; | |
4415 struct ipa_agg_replacement_value *aggval; | 5235 struct ipa_agg_replacement_value *aggval; |
4416 int i, ec, count; | 5236 int i, ec, count; |
4417 | 5237 |
4418 aggval = ipa_get_agg_replacements_for_node (node); | 5238 aggval = ipa_get_agg_replacements_for_node (node); |
4419 if (!aggval) | 5239 if (!aggval) |
4425 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) | 5245 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) |
4426 if (aggval->index >= ec) | 5246 if (aggval->index >= ec) |
4427 return false; | 5247 return false; |
4428 | 5248 |
4429 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node); | 5249 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node); |
4430 if (orig_caller_info->ipcp_orig_node) | |
4431 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node); | |
4432 | 5250 |
4433 for (i = 0; i < count; i++) | 5251 for (i = 0; i < count; i++) |
4434 { | 5252 { |
4435 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>(); | 5253 class ipcp_param_lattices *plats; |
4436 struct ipcp_param_lattices *plats; | |
4437 bool interesting = false; | 5254 bool interesting = false; |
4438 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) | 5255 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) |
4439 if (aggval->index == i) | 5256 if (aggval->index == i) |
4440 { | 5257 { |
4441 interesting = true; | 5258 interesting = true; |
4446 | 5263 |
4447 plats = ipa_get_parm_lattices (orig_node_info, aggval->index); | 5264 plats = ipa_get_parm_lattices (orig_node_info, aggval->index); |
4448 if (plats->aggs_bottom) | 5265 if (plats->aggs_bottom) |
4449 return false; | 5266 return false; |
4450 | 5267 |
4451 values = intersect_aggregates_with_edge (cs, i, values); | 5268 vec<ipa_agg_value> values = intersect_aggregates_with_edge (cs, i, vNULL); |
4452 if (!values.exists ()) | 5269 if (!values.exists ()) |
4453 return false; | 5270 return false; |
4454 | 5271 |
4455 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) | 5272 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) |
4456 if (aggval->index == i) | 5273 if (aggval->index == i) |
4457 { | 5274 { |
4458 struct ipa_agg_jf_item *item; | 5275 struct ipa_agg_value *item; |
4459 int j; | 5276 int j; |
4460 bool found = false; | 5277 bool found = false; |
4461 FOR_EACH_VEC_ELT (values, j, item) | 5278 FOR_EACH_VEC_ELT (values, j, item) |
4462 if (item->value | 5279 if (item->value |
4463 && item->offset == av->offset | 5280 && item->offset == av->offset |
4470 { | 5287 { |
4471 values.release (); | 5288 values.release (); |
4472 return false; | 5289 return false; |
4473 } | 5290 } |
4474 } | 5291 } |
5292 values.release (); | |
4475 } | 5293 } |
4476 return true; | 5294 return true; |
4477 } | 5295 } |
4478 | 5296 |
4479 /* Given an original NODE and a VAL for which we have already created a | 5297 /* Given an original NODE and a VAL for which we have already created a |
4589 aggvals = aggvals->next; | 5407 aggvals = aggvals->next; |
4590 } | 5408 } |
4591 return false; | 5409 return false; |
4592 } | 5410 } |
4593 | 5411 |
4594 /* Return true if offset is minus one because source of a polymorphic contect | 5412 /* Return true if offset is minus one because source of a polymorphic context |
4595 cannot be an aggregate value. */ | 5413 cannot be an aggregate value. */ |
4596 | 5414 |
4597 DEBUG_FUNCTION bool | 5415 DEBUG_FUNCTION bool |
4598 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *, | 5416 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *, |
4599 int , HOST_WIDE_INT offset, | 5417 int , HOST_WIDE_INT offset, |
4600 ipa_polymorphic_call_context) | 5418 ipa_polymorphic_call_context) |
4601 { | 5419 { |
4602 return offset == -1; | 5420 return offset == -1; |
4603 } | 5421 } |
4604 | 5422 |
4605 /* Decide wheter to create a special version of NODE for value VAL of parameter | 5423 /* Decide whether to create a special version of NODE for value VAL of parameter |
4606 at the given INDEX. If OFFSET is -1, the value is for the parameter itself, | 5424 at the given INDEX. If OFFSET is -1, the value is for the parameter itself, |
4607 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS, | 5425 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS, |
4608 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */ | 5426 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */ |
4609 | 5427 |
4610 template <typename valtype> | 5428 template <typename valtype> |
4621 if (val->spec_node) | 5439 if (val->spec_node) |
4622 { | 5440 { |
4623 perhaps_add_new_callers (node, val); | 5441 perhaps_add_new_callers (node, val); |
4624 return false; | 5442 return false; |
4625 } | 5443 } |
4626 else if (val->local_size_cost + overall_size > max_new_size) | 5444 else if (val->local_size_cost + overall_size > get_max_overall_size (node)) |
4627 { | 5445 { |
4628 if (dump_file && (dump_flags & TDF_DETAILS)) | 5446 if (dump_file && (dump_flags & TDF_DETAILS)) |
4629 fprintf (dump_file, " Ignoring candidate value because " | 5447 fprintf (dump_file, " Ignoring candidate value because " |
4630 "max_new_size would be reached with %li.\n", | 5448 "maximum unit size would be reached with %li.\n", |
4631 val->local_size_cost + overall_size); | 5449 val->local_size_cost + overall_size); |
4632 return false; | 5450 return false; |
4633 } | 5451 } |
4634 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum, | 5452 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum, |
4635 &caller_count)) | 5453 &caller_count)) |
4687 /* Decide whether and what specialized clones of NODE should be created. */ | 5505 /* Decide whether and what specialized clones of NODE should be created. */ |
4688 | 5506 |
4689 static bool | 5507 static bool |
4690 decide_whether_version_node (struct cgraph_node *node) | 5508 decide_whether_version_node (struct cgraph_node *node) |
4691 { | 5509 { |
4692 struct ipa_node_params *info = IPA_NODE_REF (node); | 5510 class ipa_node_params *info = IPA_NODE_REF (node); |
4693 int i, count = ipa_get_param_count (info); | 5511 int i, count = ipa_get_param_count (info); |
4694 vec<tree> known_csts; | 5512 vec<tree> known_csts; |
4695 vec<ipa_polymorphic_call_context> known_contexts; | 5513 vec<ipa_polymorphic_call_context> known_contexts; |
4696 vec<ipa_agg_jump_function> known_aggs = vNULL; | |
4697 bool ret = false; | 5514 bool ret = false; |
4698 | 5515 |
4699 if (count == 0) | 5516 if (count == 0) |
4700 return false; | 5517 return false; |
4701 | 5518 |
4702 if (dump_file && (dump_flags & TDF_DETAILS)) | 5519 if (dump_file && (dump_flags & TDF_DETAILS)) |
4703 fprintf (dump_file, "\nEvaluating opportunities for %s.\n", | 5520 fprintf (dump_file, "\nEvaluating opportunities for %s.\n", |
4704 node->dump_name ()); | 5521 node->dump_name ()); |
4705 | 5522 |
4706 gather_context_independent_values (info, &known_csts, &known_contexts, | 5523 gather_context_independent_values (info, &known_csts, &known_contexts, |
4707 info->do_clone_for_all_contexts ? &known_aggs | 5524 NULL, NULL); |
4708 : NULL, NULL); | |
4709 | 5525 |
4710 for (i = 0; i < count;i++) | 5526 for (i = 0; i < count;i++) |
4711 { | 5527 { |
4712 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 5528 class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
4713 ipcp_lattice<tree> *lat = &plats->itself; | 5529 ipcp_lattice<tree> *lat = &plats->itself; |
4714 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; | 5530 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; |
4715 | 5531 |
4716 if (!lat->bottom | 5532 if (!lat->bottom |
4717 && !known_csts[i]) | 5533 && !known_csts[i]) |
4750 } | 5566 } |
4751 | 5567 |
4752 if (info->do_clone_for_all_contexts) | 5568 if (info->do_clone_for_all_contexts) |
4753 { | 5569 { |
4754 struct cgraph_node *clone; | 5570 struct cgraph_node *clone; |
4755 vec<cgraph_edge *> callers; | 5571 vec<cgraph_edge *> callers = node->collect_callers (); |
5572 | |
5573 for (int i = callers.length () - 1; i >= 0; i--) | |
5574 { | |
5575 cgraph_edge *cs = callers[i]; | |
5576 class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
5577 | |
5578 if (caller_info && caller_info->node_dead) | |
5579 callers.unordered_remove (i); | |
5580 } | |
5581 | |
5582 if (!adjust_callers_for_value_intersection (callers, node)) | |
5583 { | |
5584 /* If node is not called by anyone, or all its caller edges are | |
5585 self-recursive, the node is not really be in use, no need to | |
5586 do cloning. */ | |
5587 callers.release (); | |
5588 known_csts.release (); | |
5589 known_contexts.release (); | |
5590 info->do_clone_for_all_contexts = false; | |
5591 return ret; | |
5592 } | |
4756 | 5593 |
4757 if (dump_file) | 5594 if (dump_file) |
4758 fprintf (dump_file, " - Creating a specialized node of %s " | 5595 fprintf (dump_file, " - Creating a specialized node of %s " |
4759 "for all known contexts.\n", node->dump_name ()); | 5596 "for all known contexts.\n", node->dump_name ()); |
4760 | 5597 |
4761 callers = node->collect_callers (); | |
4762 find_more_scalar_values_for_callers_subset (node, known_csts, callers); | 5598 find_more_scalar_values_for_callers_subset (node, known_csts, callers); |
4763 find_more_contexts_for_caller_subset (node, &known_contexts, callers); | 5599 find_more_contexts_for_caller_subset (node, &known_contexts, callers); |
4764 ipa_agg_replacement_value *aggvals | 5600 ipa_agg_replacement_value *aggvals |
4765 = find_aggregate_values_for_callers_subset (node, callers); | 5601 = find_aggregate_values_for_callers_subset (node, callers); |
4766 | 5602 |
4772 clone = create_specialized_node (node, known_csts, known_contexts, | 5608 clone = create_specialized_node (node, known_csts, known_contexts, |
4773 aggvals, callers); | 5609 aggvals, callers); |
4774 info = IPA_NODE_REF (node); | 5610 info = IPA_NODE_REF (node); |
4775 info->do_clone_for_all_contexts = false; | 5611 info->do_clone_for_all_contexts = false; |
4776 IPA_NODE_REF (clone)->is_all_contexts_clone = true; | 5612 IPA_NODE_REF (clone)->is_all_contexts_clone = true; |
4777 for (i = 0; i < count; i++) | |
4778 vec_free (known_aggs[i].items); | |
4779 known_aggs.release (); | |
4780 ret = true; | 5613 ret = true; |
4781 } | 5614 } |
4782 else | 5615 else |
4783 { | 5616 { |
4784 known_csts.release (); | 5617 known_csts.release (); |
4797 | 5630 |
4798 for (cs = node->callees; cs; cs = cs->next_callee) | 5631 for (cs = node->callees; cs; cs = cs->next_callee) |
4799 if (ipa_edge_within_scc (cs)) | 5632 if (ipa_edge_within_scc (cs)) |
4800 { | 5633 { |
4801 struct cgraph_node *callee; | 5634 struct cgraph_node *callee; |
4802 struct ipa_node_params *info; | 5635 class ipa_node_params *info; |
4803 | 5636 |
4804 callee = cs->callee->function_symbol (NULL); | 5637 callee = cs->callee->function_symbol (NULL); |
4805 info = IPA_NODE_REF (callee); | 5638 info = IPA_NODE_REF (callee); |
4806 | 5639 |
4807 if (info->node_dead) | 5640 if (info && info->node_dead) |
4808 { | 5641 { |
4809 info->node_dead = 0; | 5642 info->node_dead = 0; |
4810 spread_undeadness (callee); | 5643 spread_undeadness (callee); |
4811 } | 5644 } |
4812 } | 5645 } |
4839 static void | 5672 static void |
4840 identify_dead_nodes (struct cgraph_node *node) | 5673 identify_dead_nodes (struct cgraph_node *node) |
4841 { | 5674 { |
4842 struct cgraph_node *v; | 5675 struct cgraph_node *v; |
4843 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | 5676 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) |
4844 if (v->local.local | 5677 if (v->local |
5678 && IPA_NODE_REF (v) | |
4845 && !v->call_for_symbol_thunks_and_aliases | 5679 && !v->call_for_symbol_thunks_and_aliases |
4846 (has_undead_caller_from_outside_scc_p, NULL, true)) | 5680 (has_undead_caller_from_outside_scc_p, NULL, true)) |
4847 IPA_NODE_REF (v)->node_dead = 1; | 5681 IPA_NODE_REF (v)->node_dead = 1; |
4848 | 5682 |
4849 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | 5683 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) |
4850 if (!IPA_NODE_REF (v)->node_dead) | 5684 if (IPA_NODE_REF (v) && !IPA_NODE_REF (v)->node_dead) |
4851 spread_undeadness (v); | 5685 spread_undeadness (v); |
4852 | 5686 |
4853 if (dump_file && (dump_flags & TDF_DETAILS)) | 5687 if (dump_file && (dump_flags & TDF_DETAILS)) |
4854 { | 5688 { |
4855 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | 5689 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) |
4856 if (IPA_NODE_REF (v)->node_dead) | 5690 if (IPA_NODE_REF (v) && IPA_NODE_REF (v)->node_dead) |
4857 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ()); | 5691 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ()); |
4858 } | 5692 } |
4859 } | 5693 } |
4860 | 5694 |
4861 /* The decision stage. Iterate over the topological order of call graph nodes | 5695 /* The decision stage. Iterate over the topological order of call graph nodes |
4862 TOPO and make specialized clones if deemed beneficial. */ | 5696 TOPO and make specialized clones if deemed beneficial. */ |
4863 | 5697 |
4864 static void | 5698 static void |
4865 ipcp_decision_stage (struct ipa_topo_info *topo) | 5699 ipcp_decision_stage (class ipa_topo_info *topo) |
4866 { | 5700 { |
4867 int i; | 5701 int i; |
4868 | 5702 |
4869 if (dump_file) | 5703 if (dump_file) |
4870 fprintf (dump_file, "\nIPA decision stage:\n\n"); | 5704 fprintf (dump_file, "\nIPA decision stage:\n\n"); |
4902 { | 5736 { |
4903 ipa_node_params *info = IPA_NODE_REF (node); | 5737 ipa_node_params *info = IPA_NODE_REF (node); |
4904 bool dumped_sth = false; | 5738 bool dumped_sth = false; |
4905 bool found_useful_result = false; | 5739 bool found_useful_result = false; |
4906 | 5740 |
4907 if (!opt_for_fn (node->decl, flag_ipa_bit_cp)) | 5741 if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info) |
4908 { | 5742 { |
4909 if (dump_file) | 5743 if (dump_file) |
4910 fprintf (dump_file, "Not considering %s for ipa bitwise propagation " | 5744 fprintf (dump_file, "Not considering %s for ipa bitwise propagation " |
4911 "; -fipa-bit-cp: disabled.\n", | 5745 "; -fipa-bit-cp: disabled.\n", |
4912 node->name ()); | 5746 node->dump_name ()); |
4913 continue; | 5747 continue; |
4914 } | 5748 } |
4915 | 5749 |
4916 if (info->ipcp_orig_node) | 5750 if (info->ipcp_orig_node) |
4917 info = IPA_NODE_REF (info->ipcp_orig_node); | 5751 info = IPA_NODE_REF (info->ipcp_orig_node); |
5752 if (!info->lattices) | |
5753 /* Newly expanded artificial thunks do not have lattices. */ | |
5754 continue; | |
4918 | 5755 |
4919 unsigned count = ipa_get_param_count (info); | 5756 unsigned count = ipa_get_param_count (info); |
4920 for (unsigned i = 0; i < count; i++) | 5757 for (unsigned i = 0; i < count; i++) |
4921 { | 5758 { |
4922 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 5759 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
4975 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | 5812 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) |
4976 { | 5813 { |
4977 ipa_node_params *info = IPA_NODE_REF (node); | 5814 ipa_node_params *info = IPA_NODE_REF (node); |
4978 bool found_useful_result = false; | 5815 bool found_useful_result = false; |
4979 | 5816 |
4980 if (!opt_for_fn (node->decl, flag_ipa_vrp)) | 5817 if (!info || !opt_for_fn (node->decl, flag_ipa_vrp)) |
4981 { | 5818 { |
4982 if (dump_file) | 5819 if (dump_file) |
4983 fprintf (dump_file, "Not considering %s for VR discovery " | 5820 fprintf (dump_file, "Not considering %s for VR discovery " |
4984 "and propagate; -fipa-ipa-vrp: disabled.\n", | 5821 "and propagate; -fipa-ipa-vrp: disabled.\n", |
4985 node->name ()); | 5822 node->dump_name ()); |
4986 continue; | 5823 continue; |
4987 } | 5824 } |
4988 | 5825 |
4989 if (info->ipcp_orig_node) | 5826 if (info->ipcp_orig_node) |
4990 info = IPA_NODE_REF (info->ipcp_orig_node); | 5827 info = IPA_NODE_REF (info->ipcp_orig_node); |
5828 if (!info->lattices) | |
5829 /* Newly expanded artificial thunks do not have lattices. */ | |
5830 continue; | |
4991 | 5831 |
4992 unsigned count = ipa_get_param_count (info); | 5832 unsigned count = ipa_get_param_count (info); |
4993 for (unsigned i = 0; i < count; i++) | 5833 for (unsigned i = 0; i < count; i++) |
4994 { | 5834 { |
4995 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 5835 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
5034 /* The IPCP driver. */ | 5874 /* The IPCP driver. */ |
5035 | 5875 |
5036 static unsigned int | 5876 static unsigned int |
5037 ipcp_driver (void) | 5877 ipcp_driver (void) |
5038 { | 5878 { |
5039 struct ipa_topo_info topo; | 5879 class ipa_topo_info topo; |
5040 | 5880 |
5041 if (edge_clone_summaries == NULL) | 5881 if (edge_clone_summaries == NULL) |
5042 edge_clone_summaries = new edge_clone_summary_t (symtab); | 5882 edge_clone_summaries = new edge_clone_summary_t (symtab); |
5043 | 5883 |
5044 ipa_check_create_node_params (); | 5884 ipa_check_create_node_params (); |
5045 ipa_check_create_edge_args (); | 5885 ipa_check_create_edge_args (); |
5886 clone_num_suffixes = new hash_map<const char *, unsigned>; | |
5046 | 5887 |
5047 if (dump_file) | 5888 if (dump_file) |
5048 { | 5889 { |
5049 fprintf (dump_file, "\nIPA structures before propagation:\n"); | 5890 fprintf (dump_file, "\nIPA structures before propagation:\n"); |
5050 if (dump_flags & TDF_DETAILS) | 5891 if (dump_flags & TDF_DETAILS) |
5062 ipcp_store_bits_results (); | 5903 ipcp_store_bits_results (); |
5063 /* Store results of value range propagation. */ | 5904 /* Store results of value range propagation. */ |
5064 ipcp_store_vr_results (); | 5905 ipcp_store_vr_results (); |
5065 | 5906 |
5066 /* Free all IPCP structures. */ | 5907 /* Free all IPCP structures. */ |
5908 delete clone_num_suffixes; | |
5067 free_toporder_info (&topo); | 5909 free_toporder_info (&topo); |
5068 delete edge_clone_summaries; | 5910 delete edge_clone_summaries; |
5069 edge_clone_summaries = NULL; | 5911 edge_clone_summaries = NULL; |
5070 ipa_free_all_structures_after_ipa_cp (); | 5912 ipa_free_all_structures_after_ipa_cp (); |
5071 if (dump_file) | 5913 if (dump_file) |
5165 void | 6007 void |
5166 ipa_cp_c_finalize (void) | 6008 ipa_cp_c_finalize (void) |
5167 { | 6009 { |
5168 max_count = profile_count::uninitialized (); | 6010 max_count = profile_count::uninitialized (); |
5169 overall_size = 0; | 6011 overall_size = 0; |
5170 max_new_size = 0; | 6012 orig_overall_size = 0; |
5171 } | 6013 ipcp_free_transformation_sum (); |
6014 } |