Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-fnsummary.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Function summary pass. | 1 /* Function summary pass. |
2 Copyright (C) 2003-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2003-2018 Free Software Foundation, Inc. |
3 Contributed by Jan Hubicka | 3 Contributed by Jan Hubicka |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
77 #include "ipa-prop.h" | 77 #include "ipa-prop.h" |
78 #include "ipa-fnsummary.h" | 78 #include "ipa-fnsummary.h" |
79 #include "cfgloop.h" | 79 #include "cfgloop.h" |
80 #include "tree-scalar-evolution.h" | 80 #include "tree-scalar-evolution.h" |
81 #include "ipa-utils.h" | 81 #include "ipa-utils.h" |
82 #include "cilk.h" | |
83 #include "cfgexpand.h" | 82 #include "cfgexpand.h" |
84 #include "gimplify.h" | 83 #include "gimplify.h" |
85 #include "stringpool.h" | 84 #include "stringpool.h" |
86 #include "attribs.h" | 85 #include "attribs.h" |
87 | 86 |
242 e->make_direct (target); | 241 e->make_direct (target); |
243 else | 242 else |
244 e->redirect_callee (target); | 243 e->redirect_callee (target); |
245 struct ipa_call_summary *es = ipa_call_summaries->get (e); | 244 struct ipa_call_summary *es = ipa_call_summaries->get (e); |
246 e->inline_failed = CIF_UNREACHABLE; | 245 e->inline_failed = CIF_UNREACHABLE; |
247 e->frequency = 0; | |
248 e->count = profile_count::zero (); | 246 e->count = profile_count::zero (); |
249 es->call_stmt_size = 0; | 247 es->call_stmt_size = 0; |
250 es->call_stmt_time = 0; | 248 es->call_stmt_time = 0; |
251 if (callee) | 249 if (callee) |
252 callee->remove_symbol_and_inline_clones (); | 250 callee->remove_symbol_and_inline_clones (); |
443 | 441 |
444 if (ipa_node_params_sum | 442 if (ipa_node_params_sum |
445 && !e->call_stmt_cannot_inline_p | 443 && !e->call_stmt_cannot_inline_p |
446 && ((clause_ptr && info->conds) || known_vals_ptr || known_contexts_ptr)) | 444 && ((clause_ptr && info->conds) || known_vals_ptr || known_contexts_ptr)) |
447 { | 445 { |
448 struct ipa_node_params *parms_info; | 446 struct ipa_node_params *caller_parms_info, *callee_pi; |
449 struct ipa_edge_args *args = IPA_EDGE_REF (e); | 447 struct ipa_edge_args *args = IPA_EDGE_REF (e); |
450 struct ipa_call_summary *es = ipa_call_summaries->get (e); | 448 struct ipa_call_summary *es = ipa_call_summaries->get (e); |
451 int i, count = ipa_get_cs_argument_count (args); | 449 int i, count = ipa_get_cs_argument_count (args); |
452 | 450 |
453 if (e->caller->global.inlined_to) | 451 if (e->caller->global.inlined_to) |
454 parms_info = IPA_NODE_REF (e->caller->global.inlined_to); | 452 caller_parms_info = IPA_NODE_REF (e->caller->global.inlined_to); |
455 else | 453 else |
456 parms_info = IPA_NODE_REF (e->caller); | 454 caller_parms_info = IPA_NODE_REF (e->caller); |
455 callee_pi = IPA_NODE_REF (e->callee); | |
457 | 456 |
458 if (count && (info->conds || known_vals_ptr)) | 457 if (count && (info->conds || known_vals_ptr)) |
459 known_vals.safe_grow_cleared (count); | 458 known_vals.safe_grow_cleared (count); |
460 if (count && (info->conds || known_aggs_ptr)) | 459 if (count && (info->conds || known_aggs_ptr)) |
461 known_aggs.safe_grow_cleared (count); | 460 known_aggs.safe_grow_cleared (count); |
463 known_contexts_ptr->safe_grow_cleared (count); | 462 known_contexts_ptr->safe_grow_cleared (count); |
464 | 463 |
465 for (i = 0; i < count; i++) | 464 for (i = 0; i < count; i++) |
466 { | 465 { |
467 struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i); | 466 struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i); |
468 tree cst = ipa_value_from_jfunc (parms_info, jf); | 467 tree cst = ipa_value_from_jfunc (caller_parms_info, jf, |
468 ipa_get_type (callee_pi, i)); | |
469 | 469 |
470 if (!cst && e->call_stmt | 470 if (!cst && e->call_stmt |
471 && i < (int)gimple_call_num_args (e->call_stmt)) | 471 && i < (int)gimple_call_num_args (e->call_stmt)) |
472 { | 472 { |
473 cst = gimple_call_arg (e->call_stmt, i); | 473 cst = gimple_call_arg (e->call_stmt, i); |
482 } | 482 } |
483 else if (inline_p && !es->param[i].change_prob) | 483 else if (inline_p && !es->param[i].change_prob) |
484 known_vals[i] = error_mark_node; | 484 known_vals[i] = error_mark_node; |
485 | 485 |
486 if (known_contexts_ptr) | 486 if (known_contexts_ptr) |
487 (*known_contexts_ptr)[i] = ipa_context_from_jfunc (parms_info, e, | 487 (*known_contexts_ptr)[i] |
488 i, jf); | 488 = ipa_context_from_jfunc (caller_parms_info, e, i, jf); |
489 /* TODO: When IPA-CP starts propagating and merging aggregate jump | 489 /* TODO: When IPA-CP starts propagating and merging aggregate jump |
490 functions, use its knowledge of the caller too, just like the | 490 functions, use its knowledge of the caller too, just like the |
491 scalar case above. */ | 491 scalar case above. */ |
492 known_aggs[i] = &jf->agg; | 492 known_aggs[i] = &jf->agg; |
493 } | 493 } |
533 gcc_checking_assert (!ipa_fn_summaries); | 533 gcc_checking_assert (!ipa_fn_summaries); |
534 ipa_fn_summaries = ipa_fn_summary_t::create_ggc (symtab); | 534 ipa_fn_summaries = ipa_fn_summary_t::create_ggc (symtab); |
535 ipa_call_summaries = new ipa_call_summary_t (symtab, false); | 535 ipa_call_summaries = new ipa_call_summary_t (symtab, false); |
536 } | 536 } |
537 | 537 |
538 /* We are called multiple time for given function; clear | 538 ipa_call_summary::~ipa_call_summary () |
539 data from previous run so they are not cumulated. */ | 539 { |
540 | |
541 void | |
542 ipa_call_summary::reset () | |
543 { | |
544 call_stmt_size = call_stmt_time = 0; | |
545 if (predicate) | 540 if (predicate) |
546 edge_predicate_pool.remove (predicate); | 541 edge_predicate_pool.remove (predicate); |
547 predicate = NULL; | 542 |
548 param.release (); | 543 param.release (); |
549 } | 544 } |
550 | 545 |
551 /* We are called multiple time for given function; clear | 546 ipa_fn_summary::~ipa_fn_summary () |
552 data from previous run so they are not cumulated. */ | 547 { |
553 | |
554 void | |
555 ipa_fn_summary::reset (struct cgraph_node *node) | |
556 { | |
557 struct cgraph_edge *e; | |
558 | |
559 self_size = 0; | |
560 estimated_stack_size = 0; | |
561 estimated_self_stack_size = 0; | |
562 stack_frame_offset = 0; | |
563 size = 0; | |
564 time = 0; | |
565 growth = 0; | |
566 scc_no = 0; | |
567 if (loop_iterations) | 548 if (loop_iterations) |
568 { | 549 edge_predicate_pool.remove (loop_iterations); |
569 edge_predicate_pool.remove (loop_iterations); | |
570 loop_iterations = NULL; | |
571 } | |
572 if (loop_stride) | 550 if (loop_stride) |
573 { | 551 edge_predicate_pool.remove (loop_stride); |
574 edge_predicate_pool.remove (loop_stride); | |
575 loop_stride = NULL; | |
576 } | |
577 if (array_index) | 552 if (array_index) |
578 { | 553 edge_predicate_pool.remove (array_index); |
579 edge_predicate_pool.remove (array_index); | |
580 array_index = NULL; | |
581 } | |
582 vec_free (conds); | 554 vec_free (conds); |
583 vec_free (size_time_table); | 555 vec_free (size_time_table); |
556 } | |
557 | |
558 void | |
559 ipa_fn_summary_t::remove_callees (cgraph_node *node) | |
560 { | |
561 cgraph_edge *e; | |
584 for (e = node->callees; e; e = e->next_callee) | 562 for (e = node->callees; e; e = e->next_callee) |
585 ipa_call_summaries->get (e)->reset (); | 563 ipa_call_summaries->remove (e); |
586 for (e = node->indirect_calls; e; e = e->next_callee) | 564 for (e = node->indirect_calls; e; e = e->next_callee) |
587 ipa_call_summaries->get (e)->reset (); | 565 ipa_call_summaries->remove (e); |
588 fp_expressions = false; | |
589 } | |
590 | |
591 /* Hook that is called by cgraph.c when a node is removed. */ | |
592 | |
593 void | |
594 ipa_fn_summary_t::remove (cgraph_node *node, ipa_fn_summary *info) | |
595 { | |
596 info->reset (node); | |
597 } | 566 } |
598 | 567 |
599 /* Same as remap_predicate_after_duplication but handle hint predicate *P. | 568 /* Same as remap_predicate_after_duplication but handle hint predicate *P. |
600 Additionally care about allocating new memory slot for updated predicate | 569 Additionally care about allocating new memory slot for updated predicate |
601 and set it to NULL when it becomes true or false (and thus uninteresting). | 570 and set it to NULL when it becomes true or false (and thus uninteresting). |
622 ipa_fn_summary_t::duplicate (cgraph_node *src, | 591 ipa_fn_summary_t::duplicate (cgraph_node *src, |
623 cgraph_node *dst, | 592 cgraph_node *dst, |
624 ipa_fn_summary *, | 593 ipa_fn_summary *, |
625 ipa_fn_summary *info) | 594 ipa_fn_summary *info) |
626 { | 595 { |
627 memcpy (info, ipa_fn_summaries->get (src), sizeof (ipa_fn_summary)); | 596 new (info) ipa_fn_summary (*ipa_fn_summaries->get (src)); |
628 /* TODO: as an optimization, we may avoid copying conditions | 597 /* TODO: as an optimization, we may avoid copying conditions |
629 that are known to be false or true. */ | 598 that are known to be false or true. */ |
630 info->conds = vec_safe_copy (info->conds); | 599 info->conds = vec_safe_copy (info->conds); |
631 | 600 |
632 /* When there are any replacements in the function body, see if we can figure | 601 /* When there are any replacements in the function body, see if we can figure |
697 /* Remap edge predicates with the same simplification as above. | 666 /* Remap edge predicates with the same simplification as above. |
698 Also copy constantness arrays. */ | 667 Also copy constantness arrays. */ |
699 for (edge = dst->callees; edge; edge = next) | 668 for (edge = dst->callees; edge; edge = next) |
700 { | 669 { |
701 predicate new_predicate; | 670 predicate new_predicate; |
702 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | 671 struct ipa_call_summary *es = ipa_call_summaries->get_create (edge); |
703 next = edge->next_callee; | 672 next = edge->next_callee; |
704 | 673 |
705 if (!edge->inline_failed) | 674 if (!edge->inline_failed) |
706 inlined_to_p = true; | 675 inlined_to_p = true; |
707 if (!es->predicate) | 676 if (!es->predicate) |
716 /* Remap indirect edge predicates with the same simplificaiton as above. | 685 /* Remap indirect edge predicates with the same simplificaiton as above. |
717 Also copy constantness arrays. */ | 686 Also copy constantness arrays. */ |
718 for (edge = dst->indirect_calls; edge; edge = next) | 687 for (edge = dst->indirect_calls; edge; edge = next) |
719 { | 688 { |
720 predicate new_predicate; | 689 predicate new_predicate; |
721 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | 690 struct ipa_call_summary *es = ipa_call_summaries->get_create (edge); |
722 next = edge->next_callee; | 691 next = edge->next_callee; |
723 | 692 |
724 gcc_checking_assert (edge->inline_failed); | 693 gcc_checking_assert (edge->inline_failed); |
725 if (!es->predicate) | 694 if (!es->predicate) |
726 continue; | 695 continue; |
776 ipa_call_summary_t::duplicate (struct cgraph_edge *src, | 745 ipa_call_summary_t::duplicate (struct cgraph_edge *src, |
777 struct cgraph_edge *dst, | 746 struct cgraph_edge *dst, |
778 struct ipa_call_summary *srcinfo, | 747 struct ipa_call_summary *srcinfo, |
779 struct ipa_call_summary *info) | 748 struct ipa_call_summary *info) |
780 { | 749 { |
781 *info = *srcinfo; | 750 new (info) ipa_call_summary (*srcinfo); |
782 info->predicate = NULL; | 751 info->predicate = NULL; |
783 edge_set_predicate (dst, srcinfo->predicate); | 752 edge_set_predicate (dst, srcinfo->predicate); |
784 info->param = srcinfo->param.copy (); | 753 info->param = srcinfo->param.copy (); |
785 if (!dst->indirect_unknown_callee && src->indirect_unknown_callee) | 754 if (!dst->indirect_unknown_callee && src->indirect_unknown_callee) |
786 { | 755 { |
789 info->call_stmt_time -= (eni_time_weights.indirect_call_cost | 758 info->call_stmt_time -= (eni_time_weights.indirect_call_cost |
790 - eni_time_weights.call_cost); | 759 - eni_time_weights.call_cost); |
791 } | 760 } |
792 } | 761 } |
793 | 762 |
794 | |
795 /* Keep edge cache consistent across edge removal. */ | |
796 | |
797 void | |
798 ipa_call_summary_t::remove (struct cgraph_edge *, | |
799 struct ipa_call_summary *sum) | |
800 { | |
801 sum->reset (); | |
802 } | |
803 | |
804 | |
805 /* Dump edge summaries associated to NODE and recursively to all clones. | 763 /* Dump edge summaries associated to NODE and recursively to all clones. |
806 Indent by INDENT. */ | 764 Indent by INDENT. */ |
807 | 765 |
808 static void | 766 static void |
809 dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node, | 767 dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node, |
815 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | 773 struct ipa_call_summary *es = ipa_call_summaries->get (edge); |
816 struct cgraph_node *callee = edge->callee->ultimate_alias_target (); | 774 struct cgraph_node *callee = edge->callee->ultimate_alias_target (); |
817 int i; | 775 int i; |
818 | 776 |
819 fprintf (f, | 777 fprintf (f, |
820 "%*s%s/%i %s\n%*s loop depth:%2i freq:%4i size:%2i" | 778 "%*s%s/%i %s\n%*s loop depth:%2i freq:%4.2f size:%2i time: %2i", |
821 " time: %2i callee size:%2i stack:%2i", | |
822 indent, "", callee->name (), callee->order, | 779 indent, "", callee->name (), callee->order, |
823 !edge->inline_failed | 780 !edge->inline_failed |
824 ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed), | 781 ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed), |
825 indent, "", es->loop_depth, edge->frequency, | 782 indent, "", es->loop_depth, edge->sreal_frequency ().to_double (), |
826 es->call_stmt_size, es->call_stmt_time, | 783 es->call_stmt_size, es->call_stmt_time); |
827 (int) ipa_fn_summaries->get (callee)->size / ipa_fn_summary::size_scale, | 784 |
828 (int) ipa_fn_summaries->get (callee)->estimated_stack_size); | 785 ipa_fn_summary *s = ipa_fn_summaries->get (callee); |
786 if (s != NULL) | |
787 fprintf (f, "callee size:%2i stack:%2i", | |
788 (int) (s->size / ipa_fn_summary::size_scale), | |
789 (int) s->estimated_stack_size); | |
829 | 790 |
830 if (es->predicate) | 791 if (es->predicate) |
831 { | 792 { |
832 fprintf (f, " predicate: "); | 793 fprintf (f, " predicate: "); |
833 es->predicate->dump (f, info->conds); | 794 es->predicate->dump (f, info->conds); |
846 fprintf (f, "%*s op%i change %f%% of time\n", indent + 2, "", i, | 807 fprintf (f, "%*s op%i change %f%% of time\n", indent + 2, "", i, |
847 prob * 100.0 / REG_BR_PROB_BASE); | 808 prob * 100.0 / REG_BR_PROB_BASE); |
848 } | 809 } |
849 if (!edge->inline_failed) | 810 if (!edge->inline_failed) |
850 { | 811 { |
812 ipa_fn_summary *s = ipa_fn_summaries->get (callee); | |
851 fprintf (f, "%*sStack frame offset %i, callee self size %i," | 813 fprintf (f, "%*sStack frame offset %i, callee self size %i," |
852 " callee size %i\n", | 814 " callee size %i\n", |
853 indent + 2, "", | 815 indent + 2, "", |
854 (int) ipa_fn_summaries->get (callee)->stack_frame_offset, | 816 (int) s->stack_frame_offset, |
855 (int) ipa_fn_summaries->get (callee)->estimated_self_stack_size, | 817 (int) s->estimated_self_stack_size, |
856 (int) ipa_fn_summaries->get (callee)->estimated_stack_size); | 818 (int) s->estimated_stack_size); |
857 dump_ipa_call_summary (f, indent + 2, callee, info); | 819 dump_ipa_call_summary (f, indent + 2, callee, info); |
858 } | 820 } |
859 } | 821 } |
860 for (edge = node->indirect_calls; edge; edge = edge->next_callee) | 822 for (edge = node->indirect_calls; edge; edge = edge->next_callee) |
861 { | 823 { |
862 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | 824 struct ipa_call_summary *es = ipa_call_summaries->get (edge); |
863 fprintf (f, "%*sindirect call loop depth:%2i freq:%4i size:%2i" | 825 fprintf (f, "%*sindirect call loop depth:%2i freq:%4.2f size:%2i" |
864 " time: %2i", | 826 " time: %2i", |
865 indent, "", | 827 indent, "", |
866 es->loop_depth, | 828 es->loop_depth, |
867 edge->frequency, es->call_stmt_size, es->call_stmt_time); | 829 edge->sreal_frequency ().to_double (), es->call_stmt_size, |
830 es->call_stmt_time); | |
868 if (es->predicate) | 831 if (es->predicate) |
869 { | 832 { |
870 fprintf (f, "predicate: "); | 833 fprintf (f, "predicate: "); |
871 es->predicate->dump (f, info->conds); | 834 es->predicate->dump (f, info->conds); |
872 } | 835 } |
880 ipa_dump_fn_summary (FILE *f, struct cgraph_node *node) | 843 ipa_dump_fn_summary (FILE *f, struct cgraph_node *node) |
881 { | 844 { |
882 if (node->definition) | 845 if (node->definition) |
883 { | 846 { |
884 struct ipa_fn_summary *s = ipa_fn_summaries->get (node); | 847 struct ipa_fn_summary *s = ipa_fn_summaries->get (node); |
885 size_time_entry *e; | 848 if (s != NULL) |
886 int i; | 849 { |
887 fprintf (f, "IPA function summary for %s/%i", node->name (), | 850 size_time_entry *e; |
888 node->order); | 851 int i; |
889 if (DECL_DISREGARD_INLINE_LIMITS (node->decl)) | 852 fprintf (f, "IPA function summary for %s", node->dump_name ()); |
890 fprintf (f, " always_inline"); | 853 if (DECL_DISREGARD_INLINE_LIMITS (node->decl)) |
891 if (s->inlinable) | 854 fprintf (f, " always_inline"); |
892 fprintf (f, " inlinable"); | 855 if (s->inlinable) |
893 if (s->contains_cilk_spawn) | 856 fprintf (f, " inlinable"); |
894 fprintf (f, " contains_cilk_spawn"); | 857 if (s->fp_expressions) |
895 if (s->fp_expressions) | 858 fprintf (f, " fp_expression"); |
896 fprintf (f, " fp_expression"); | 859 fprintf (f, "\n global time: %f\n", s->time.to_double ()); |
897 fprintf (f, "\n global time: %f\n", s->time.to_double ()); | 860 fprintf (f, " self size: %i\n", s->self_size); |
898 fprintf (f, " self size: %i\n", s->self_size); | 861 fprintf (f, " global size: %i\n", s->size); |
899 fprintf (f, " global size: %i\n", s->size); | 862 fprintf (f, " min size: %i\n", s->min_size); |
900 fprintf (f, " min size: %i\n", s->min_size); | 863 fprintf (f, " self stack: %i\n", |
901 fprintf (f, " self stack: %i\n", | 864 (int) s->estimated_self_stack_size); |
902 (int) s->estimated_self_stack_size); | 865 fprintf (f, " global stack: %i\n", (int) s->estimated_stack_size); |
903 fprintf (f, " global stack: %i\n", (int) s->estimated_stack_size); | 866 if (s->growth) |
904 if (s->growth) | 867 fprintf (f, " estimated growth:%i\n", (int) s->growth); |
905 fprintf (f, " estimated growth:%i\n", (int) s->growth); | 868 if (s->scc_no) |
906 if (s->scc_no) | 869 fprintf (f, " In SCC: %i\n", (int) s->scc_no); |
907 fprintf (f, " In SCC: %i\n", (int) s->scc_no); | 870 for (i = 0; vec_safe_iterate (s->size_time_table, i, &e); i++) |
908 for (i = 0; vec_safe_iterate (s->size_time_table, i, &e); i++) | |
909 { | |
910 fprintf (f, " size:%f, time:%f", | |
911 (double) e->size / ipa_fn_summary::size_scale, | |
912 e->time.to_double ()); | |
913 if (e->exec_predicate != true) | |
914 { | 871 { |
915 fprintf (f, ", executed if:"); | 872 fprintf (f, " size:%f, time:%f", |
916 e->exec_predicate.dump (f, s->conds, 0); | 873 (double) e->size / ipa_fn_summary::size_scale, |
874 e->time.to_double ()); | |
875 if (e->exec_predicate != true) | |
876 { | |
877 fprintf (f, ", executed if:"); | |
878 e->exec_predicate.dump (f, s->conds, 0); | |
879 } | |
880 if (e->exec_predicate != e->nonconst_predicate) | |
881 { | |
882 fprintf (f, ", nonconst if:"); | |
883 e->nonconst_predicate.dump (f, s->conds, 0); | |
884 } | |
885 fprintf (f, "\n"); | |
917 } | 886 } |
918 if (e->exec_predicate != e->nonconst_predicate) | 887 if (s->loop_iterations) |
919 { | 888 { |
920 fprintf (f, ", nonconst if:"); | 889 fprintf (f, " loop iterations:"); |
921 e->nonconst_predicate.dump (f, s->conds, 0); | 890 s->loop_iterations->dump (f, s->conds); |
922 } | 891 } |
892 if (s->loop_stride) | |
893 { | |
894 fprintf (f, " loop stride:"); | |
895 s->loop_stride->dump (f, s->conds); | |
896 } | |
897 if (s->array_index) | |
898 { | |
899 fprintf (f, " array index:"); | |
900 s->array_index->dump (f, s->conds); | |
901 } | |
902 fprintf (f, " calls:\n"); | |
903 dump_ipa_call_summary (f, 4, node, s); | |
923 fprintf (f, "\n"); | 904 fprintf (f, "\n"); |
924 } | 905 } |
925 if (s->loop_iterations) | 906 else |
926 { | 907 fprintf (f, "IPA summary for %s is missing.\n", node->dump_name ()); |
927 fprintf (f, " loop iterations:"); | |
928 s->loop_iterations->dump (f, s->conds); | |
929 } | |
930 if (s->loop_stride) | |
931 { | |
932 fprintf (f, " loop stride:"); | |
933 s->loop_stride->dump (f, s->conds); | |
934 } | |
935 if (s->array_index) | |
936 { | |
937 fprintf (f, " array index:"); | |
938 s->array_index->dump (f, s->conds); | |
939 } | |
940 fprintf (f, " calls:\n"); | |
941 dump_ipa_call_summary (f, 4, node, s); | |
942 fprintf (f, "\n"); | |
943 } | 908 } |
944 } | 909 } |
945 | 910 |
946 DEBUG_FUNCTION void | 911 DEBUG_FUNCTION void |
947 ipa_debug_fn_summary (struct cgraph_node *node) | 912 ipa_debug_fn_summary (struct cgraph_node *node) |
1324 { | 1289 { |
1325 tree cl = gimple_switch_label (last, case_idx); | 1290 tree cl = gimple_switch_label (last, case_idx); |
1326 tree min, max; | 1291 tree min, max; |
1327 predicate p; | 1292 predicate p; |
1328 | 1293 |
1329 e = find_edge (bb, label_to_block (CASE_LABEL (cl))); | 1294 e = gimple_switch_edge (cfun, last, case_idx); |
1330 min = CASE_LOW (cl); | 1295 min = CASE_LOW (cl); |
1331 max = CASE_HIGH (cl); | 1296 max = CASE_HIGH (cl); |
1332 | 1297 |
1333 /* For default we might want to construct predicate that none | 1298 /* For default we might want to construct predicate that none |
1334 of cases is met, but it is bit hard to do not having negations | 1299 of cases is met, but it is bit hard to do not having negations |
1483 p2 = will_be_nonconstant_expr_predicate (info, summary, | 1448 p2 = will_be_nonconstant_expr_predicate (info, summary, |
1484 TREE_OPERAND (expr, 2), | 1449 TREE_OPERAND (expr, 2), |
1485 nonconstant_names); | 1450 nonconstant_names); |
1486 return p2.or_with (summary->conds, p1); | 1451 return p2.or_with (summary->conds, p1); |
1487 } | 1452 } |
1453 else if (TREE_CODE (expr) == CALL_EXPR) | |
1454 return true; | |
1488 else | 1455 else |
1489 { | 1456 { |
1490 debug_tree (expr); | 1457 debug_tree (expr); |
1491 gcc_unreachable (); | 1458 gcc_unreachable (); |
1492 } | 1459 } |
1589 return op_non_const; | 1556 return op_non_const; |
1590 } | 1557 } |
1591 | 1558 |
1592 struct record_modified_bb_info | 1559 struct record_modified_bb_info |
1593 { | 1560 { |
1561 tree op; | |
1594 bitmap bb_set; | 1562 bitmap bb_set; |
1595 gimple *stmt; | 1563 gimple *stmt; |
1596 }; | 1564 }; |
1597 | 1565 |
1598 /* Value is initialized in INIT_BB and used in USE_BB. We want to copute | 1566 /* Value is initialized in INIT_BB and used in USE_BB. We want to copute |
1599 probability how often it changes between USE_BB. | 1567 probability how often it changes between USE_BB. |
1600 INIT_BB->frequency/USE_BB->frequency is an estimate, but if INIT_BB | 1568 INIT_BB->count/USE_BB->count is an estimate, but if INIT_BB |
1601 is in different loop nest, we can do better. | 1569 is in different loop nest, we can do better. |
1602 This is all just estimate. In theory we look for minimal cut separating | 1570 This is all just estimate. In theory we look for minimal cut separating |
1603 INIT_BB and USE_BB, but we only want to anticipate loop invariant motion | 1571 INIT_BB and USE_BB, but we only want to anticipate loop invariant motion |
1604 anyway. */ | 1572 anyway. */ |
1605 | 1573 |
1606 static basic_block | 1574 static basic_block |
1607 get_minimal_bb (basic_block init_bb, basic_block use_bb) | 1575 get_minimal_bb (basic_block init_bb, basic_block use_bb) |
1608 { | 1576 { |
1609 struct loop *l = find_common_loop (init_bb->loop_father, use_bb->loop_father); | 1577 struct loop *l = find_common_loop (init_bb->loop_father, use_bb->loop_father); |
1610 if (l && l->header->frequency < init_bb->frequency) | 1578 if (l && l->header->count < init_bb->count) |
1611 return l->header; | 1579 return l->header; |
1612 return init_bb; | 1580 return init_bb; |
1613 } | 1581 } |
1614 | 1582 |
1615 /* Callback of walk_aliased_vdefs. Records basic blocks where the value may be | 1583 /* Callback of walk_aliased_vdefs. Records basic blocks where the value may be |
1619 record_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) | 1587 record_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) |
1620 { | 1588 { |
1621 struct record_modified_bb_info *info = | 1589 struct record_modified_bb_info *info = |
1622 (struct record_modified_bb_info *) data; | 1590 (struct record_modified_bb_info *) data; |
1623 if (SSA_NAME_DEF_STMT (vdef) == info->stmt) | 1591 if (SSA_NAME_DEF_STMT (vdef) == info->stmt) |
1592 return false; | |
1593 if (gimple_clobber_p (SSA_NAME_DEF_STMT (vdef))) | |
1624 return false; | 1594 return false; |
1625 bitmap_set_bit (info->bb_set, | 1595 bitmap_set_bit (info->bb_set, |
1626 SSA_NAME_IS_DEFAULT_DEF (vdef) | 1596 SSA_NAME_IS_DEFAULT_DEF (vdef) |
1627 ? ENTRY_BLOCK_PTR_FOR_FN (cfun)->index | 1597 ? ENTRY_BLOCK_PTR_FOR_FN (cfun)->index |
1628 : get_minimal_bb | 1598 : get_minimal_bb |
1629 (gimple_bb (SSA_NAME_DEF_STMT (vdef)), | 1599 (gimple_bb (SSA_NAME_DEF_STMT (vdef)), |
1630 gimple_bb (info->stmt))->index); | 1600 gimple_bb (info->stmt))->index); |
1601 if (dump_file) | |
1602 { | |
1603 fprintf (dump_file, " Param "); | |
1604 print_generic_expr (dump_file, info->op, TDF_SLIM); | |
1605 fprintf (dump_file, " changed at bb %i, minimal: %i stmt: ", | |
1606 gimple_bb (SSA_NAME_DEF_STMT (vdef))->index, | |
1607 get_minimal_bb | |
1608 (gimple_bb (SSA_NAME_DEF_STMT (vdef)), | |
1609 gimple_bb (info->stmt))->index); | |
1610 print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (vdef), 0); | |
1611 } | |
1631 return false; | 1612 return false; |
1632 } | 1613 } |
1633 | 1614 |
1634 /* Return probability (based on REG_BR_PROB_BASE) that I-th parameter of STMT | 1615 /* Return probability (based on REG_BR_PROB_BASE) that I-th parameter of STMT |
1635 will change since last invocation of STMT. | 1616 will change since last invocation of STMT. |
1659 | 1640 |
1660 We do an conservative estimate: when call is executed N times more often | 1641 We do an conservative estimate: when call is executed N times more often |
1661 than the statement defining value, we take the frequency 1/N. */ | 1642 than the statement defining value, we take the frequency 1/N. */ |
1662 if (TREE_CODE (base) == SSA_NAME) | 1643 if (TREE_CODE (base) == SSA_NAME) |
1663 { | 1644 { |
1664 int init_freq; | 1645 profile_count init_count; |
1665 | 1646 |
1666 if (!bb->frequency) | 1647 if (!bb->count.nonzero_p ()) |
1667 return REG_BR_PROB_BASE; | 1648 return REG_BR_PROB_BASE; |
1668 | 1649 |
1669 if (SSA_NAME_IS_DEFAULT_DEF (base)) | 1650 if (SSA_NAME_IS_DEFAULT_DEF (base)) |
1670 init_freq = ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency; | 1651 init_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; |
1671 else | 1652 else |
1672 init_freq = get_minimal_bb | 1653 init_count = get_minimal_bb |
1673 (gimple_bb (SSA_NAME_DEF_STMT (base)), | 1654 (gimple_bb (SSA_NAME_DEF_STMT (base)), |
1674 gimple_bb (stmt))->frequency; | 1655 gimple_bb (stmt))->count; |
1675 | 1656 |
1676 if (!init_freq) | 1657 if (init_count < bb->count) |
1677 init_freq = 1; | 1658 return MAX ((init_count.to_sreal_scale (bb->count) |
1678 if (init_freq < bb->frequency) | 1659 * REG_BR_PROB_BASE).to_int (), 1); |
1679 return MAX (GCOV_COMPUTE_SCALE (init_freq, bb->frequency), 1); | 1660 return REG_BR_PROB_BASE; |
1680 else | |
1681 return REG_BR_PROB_BASE; | |
1682 } | 1661 } |
1683 else | 1662 else |
1684 { | 1663 { |
1685 ao_ref refd; | 1664 ao_ref refd; |
1686 int max; | 1665 profile_count max = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; |
1687 struct record_modified_bb_info info; | 1666 struct record_modified_bb_info info; |
1688 bitmap_iterator bi; | |
1689 unsigned index; | |
1690 tree init = ctor_for_folding (base); | 1667 tree init = ctor_for_folding (base); |
1691 | 1668 |
1692 if (init != error_mark_node) | 1669 if (init != error_mark_node) |
1693 return 0; | 1670 return 0; |
1694 if (!bb->frequency) | 1671 if (!bb->count.nonzero_p ()) |
1695 return REG_BR_PROB_BASE; | 1672 return REG_BR_PROB_BASE; |
1673 if (dump_file) | |
1674 { | |
1675 fprintf (dump_file, " Analyzing param change probablity of "); | |
1676 print_generic_expr (dump_file, op, TDF_SLIM); | |
1677 fprintf (dump_file, "\n"); | |
1678 } | |
1696 ao_ref_init (&refd, op); | 1679 ao_ref_init (&refd, op); |
1680 info.op = op; | |
1697 info.stmt = stmt; | 1681 info.stmt = stmt; |
1698 info.bb_set = BITMAP_ALLOC (NULL); | 1682 info.bb_set = BITMAP_ALLOC (NULL); |
1699 walk_aliased_vdefs (&refd, gimple_vuse (stmt), record_modified, &info, | 1683 walk_aliased_vdefs (&refd, gimple_vuse (stmt), record_modified, &info, |
1700 NULL); | 1684 NULL); |
1701 if (bitmap_bit_p (info.bb_set, bb->index)) | 1685 if (bitmap_bit_p (info.bb_set, bb->index)) |
1702 { | 1686 { |
1687 if (dump_file) | |
1688 fprintf (dump_file, " Set in same BB as used.\n"); | |
1703 BITMAP_FREE (info.bb_set); | 1689 BITMAP_FREE (info.bb_set); |
1704 return REG_BR_PROB_BASE; | 1690 return REG_BR_PROB_BASE; |
1705 } | 1691 } |
1706 | 1692 |
1707 /* Assume that every memory is initialized at entry. | 1693 bitmap_iterator bi; |
1708 TODO: Can we easilly determine if value is always defined | 1694 unsigned index; |
1709 and thus we may skip entry block? */ | 1695 /* Lookup the most frequent update of the value and believe that |
1710 if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency) | 1696 it dominates all the other; precise analysis here is difficult. */ |
1711 max = ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency; | |
1712 else | |
1713 max = 1; | |
1714 | |
1715 EXECUTE_IF_SET_IN_BITMAP (info.bb_set, 0, index, bi) | 1697 EXECUTE_IF_SET_IN_BITMAP (info.bb_set, 0, index, bi) |
1716 max = MIN (max, BASIC_BLOCK_FOR_FN (cfun, index)->frequency); | 1698 max = max.max (BASIC_BLOCK_FOR_FN (cfun, index)->count); |
1699 if (dump_file) | |
1700 { | |
1701 fprintf (dump_file, " Set with count "); | |
1702 max.dump (dump_file); | |
1703 fprintf (dump_file, " and used with count "); | |
1704 bb->count.dump (dump_file); | |
1705 fprintf (dump_file, " freq %f\n", | |
1706 max.to_sreal_scale (bb->count).to_double ()); | |
1707 } | |
1717 | 1708 |
1718 BITMAP_FREE (info.bb_set); | 1709 BITMAP_FREE (info.bb_set); |
1719 if (max < bb->frequency) | 1710 if (max < bb->count) |
1720 return MAX (GCOV_COMPUTE_SCALE (max, bb->frequency), 1); | 1711 return MAX ((max.to_sreal_scale (bb->count) |
1721 else | 1712 * REG_BR_PROB_BASE).to_int (), 1); |
1722 return REG_BR_PROB_BASE; | 1713 return REG_BR_PROB_BASE; |
1723 } | 1714 } |
1724 } | 1715 } |
1725 | 1716 |
1726 /* Find whether a basic block BB is the final block of a (half) diamond CFG | 1717 /* Find whether a basic block BB is the final block of a (half) diamond CFG |
1727 sub-graph and if the predicate the condition depends on is known. If so, | 1718 sub-graph and if the predicate the condition depends on is known. If so, |
1858 | 1849 |
1859 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) | 1850 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) |
1860 { | 1851 { |
1861 gimple *stmt = gsi_stmt (bsi); | 1852 gimple *stmt = gsi_stmt (bsi); |
1862 if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT) | 1853 if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT) |
1854 || gimple_call_builtin_p (stmt, BUILT_IN_EXPECT_WITH_PROBABILITY) | |
1863 || gimple_call_internal_p (stmt, IFN_BUILTIN_EXPECT)) | 1855 || gimple_call_internal_p (stmt, IFN_BUILTIN_EXPECT)) |
1864 { | 1856 { |
1865 tree var = gimple_call_lhs (stmt); | 1857 tree var = gimple_call_lhs (stmt); |
1866 tree arg = gimple_call_arg (stmt, 0); | 1858 tree arg = gimple_call_arg (stmt, 0); |
1867 use_operand_p use_p; | 1859 use_operand_p use_p; |
1982 int size = 2; | 1974 int size = 2; |
1983 /* Benefits are scaled by probability of elimination that is in range | 1975 /* Benefits are scaled by probability of elimination that is in range |
1984 <0,2>. */ | 1976 <0,2>. */ |
1985 basic_block bb; | 1977 basic_block bb; |
1986 struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); | 1978 struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); |
1987 int freq; | 1979 sreal freq; |
1988 struct ipa_fn_summary *info = ipa_fn_summaries->get (node); | 1980 struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node); |
1989 predicate bb_predicate; | 1981 predicate bb_predicate; |
1990 struct ipa_func_body_info fbi; | 1982 struct ipa_func_body_info fbi; |
1991 vec<predicate> nonconstant_names = vNULL; | 1983 vec<predicate> nonconstant_names = vNULL; |
1992 int nblocks, n; | 1984 int nblocks, n; |
1993 int *order; | 1985 int *order; |
2048 order = XNEWVEC (int, n_basic_blocks_for_fn (cfun)); | 2040 order = XNEWVEC (int, n_basic_blocks_for_fn (cfun)); |
2049 nblocks = pre_and_rev_post_order_compute (NULL, order, false); | 2041 nblocks = pre_and_rev_post_order_compute (NULL, order, false); |
2050 for (n = 0; n < nblocks; n++) | 2042 for (n = 0; n < nblocks; n++) |
2051 { | 2043 { |
2052 bb = BASIC_BLOCK_FOR_FN (cfun, order[n]); | 2044 bb = BASIC_BLOCK_FOR_FN (cfun, order[n]); |
2053 freq = compute_call_stmt_bb_frequency (node->decl, bb); | 2045 freq = bb->count.to_sreal_scale (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count); |
2054 if (clobber_only_eh_bb_p (bb)) | 2046 if (clobber_only_eh_bb_p (bb)) |
2055 { | 2047 { |
2056 if (dump_file && (dump_flags & TDF_DETAILS)) | 2048 if (dump_file && (dump_flags & TDF_DETAILS)) |
2057 fprintf (dump_file, "\n Ignoring BB %i;" | 2049 fprintf (dump_file, "\n Ignoring BB %i;" |
2058 " it will be optimized away by cleanup_clobbers\n", | 2050 " it will be optimized away by cleanup_clobbers\n", |
2123 if (dump_file && (dump_flags & TDF_DETAILS)) | 2115 if (dump_file && (dump_flags & TDF_DETAILS)) |
2124 { | 2116 { |
2125 fprintf (dump_file, " "); | 2117 fprintf (dump_file, " "); |
2126 print_gimple_stmt (dump_file, stmt, 0); | 2118 print_gimple_stmt (dump_file, stmt, 0); |
2127 fprintf (dump_file, "\t\tfreq:%3.2f size:%3i time:%3i\n", | 2119 fprintf (dump_file, "\t\tfreq:%3.2f size:%3i time:%3i\n", |
2128 ((double) freq) / CGRAPH_FREQ_BASE, this_size, | 2120 freq.to_double (), this_size, |
2129 this_time); | 2121 this_time); |
2130 } | 2122 } |
2131 | 2123 |
2132 if (gimple_assign_load_p (stmt) && nonconstant_names.exists ()) | 2124 if (gimple_assign_load_p (stmt) && nonconstant_names.exists ()) |
2133 { | 2125 { |
2151 | 2143 |
2152 if (is_gimple_call (stmt) | 2144 if (is_gimple_call (stmt) |
2153 && !gimple_call_internal_p (stmt)) | 2145 && !gimple_call_internal_p (stmt)) |
2154 { | 2146 { |
2155 struct cgraph_edge *edge = node->get_edge (stmt); | 2147 struct cgraph_edge *edge = node->get_edge (stmt); |
2156 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | 2148 ipa_call_summary *es = ipa_call_summaries->get_create (edge); |
2157 | 2149 |
2158 /* Special case: results of BUILT_IN_CONSTANT_P will be always | 2150 /* Special case: results of BUILT_IN_CONSTANT_P will be always |
2159 resolved as constant. We however don't want to optimize | 2151 resolved as constant. We however don't want to optimize |
2160 out the cgraph edges. */ | 2152 out the cgraph edges. */ |
2161 if (nonconstant_names.exists () | 2153 if (nonconstant_names.exists () |
2197 stmt, nonconstant_names); | 2189 stmt, nonconstant_names); |
2198 else | 2190 else |
2199 will_be_nonconstant = true; | 2191 will_be_nonconstant = true; |
2200 if (this_time || this_size) | 2192 if (this_time || this_size) |
2201 { | 2193 { |
2202 this_time *= freq; | 2194 sreal final_time = (sreal)this_time * freq; |
2203 | 2195 |
2204 prob = eliminated_by_inlining_prob (stmt); | 2196 prob = eliminated_by_inlining_prob (stmt); |
2205 if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS)) | 2197 if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS)) |
2206 fprintf (dump_file, | 2198 fprintf (dump_file, |
2207 "\t\t50%% will be eliminated by inlining\n"); | 2199 "\t\t50%% will be eliminated by inlining\n"); |
2214 to happen, but we can not do that for call statements | 2206 to happen, but we can not do that for call statements |
2215 because edges are accounted specially. */ | 2207 because edges are accounted specially. */ |
2216 | 2208 |
2217 if (*(is_gimple_call (stmt) ? &bb_predicate : &p) != false) | 2209 if (*(is_gimple_call (stmt) ? &bb_predicate : &p) != false) |
2218 { | 2210 { |
2219 time += this_time; | 2211 time += final_time; |
2220 size += this_size; | 2212 size += this_size; |
2221 } | 2213 } |
2222 | 2214 |
2223 /* We account everything but the calls. Calls have their own | 2215 /* We account everything but the calls. Calls have their own |
2224 size/time info attached to cgraph edges. This is necessary | 2216 size/time info attached to cgraph edges. This is necessary |
2227 { | 2219 { |
2228 if (prob) | 2220 if (prob) |
2229 { | 2221 { |
2230 predicate ip = bb_predicate & predicate::not_inlined (); | 2222 predicate ip = bb_predicate & predicate::not_inlined (); |
2231 info->account_size_time (this_size * prob, | 2223 info->account_size_time (this_size * prob, |
2232 (sreal)(this_time * prob) | 2224 (this_time * prob) / 2, ip, |
2233 / (CGRAPH_FREQ_BASE * 2), ip, | |
2234 p); | 2225 p); |
2235 } | 2226 } |
2236 if (prob != 2) | 2227 if (prob != 2) |
2237 info->account_size_time (this_size * (2 - prob), | 2228 info->account_size_time (this_size * (2 - prob), |
2238 (sreal)(this_time * (2 - prob)) | 2229 (this_time * (2 - prob) / 2), |
2239 / (CGRAPH_FREQ_BASE * 2), | |
2240 bb_predicate, | 2230 bb_predicate, |
2241 p); | 2231 p); |
2242 } | 2232 } |
2243 | 2233 |
2244 if (!info->fp_expressions && fp_expression_p (stmt)) | 2234 if (!info->fp_expressions && fp_expression_p (stmt)) |
2251 gcc_assert (time >= 0); | 2241 gcc_assert (time >= 0); |
2252 gcc_assert (size >= 0); | 2242 gcc_assert (size >= 0); |
2253 } | 2243 } |
2254 } | 2244 } |
2255 } | 2245 } |
2256 set_hint_predicate (&ipa_fn_summaries->get (node)->array_index, array_index); | 2246 set_hint_predicate (&ipa_fn_summaries->get_create (node)->array_index, |
2257 time = time / CGRAPH_FREQ_BASE; | 2247 array_index); |
2258 free (order); | 2248 free (order); |
2259 | 2249 |
2260 if (nonconstant_names.exists () && !early) | 2250 if (nonconstant_names.exists () && !early) |
2261 { | 2251 { |
2262 struct loop *loop; | 2252 struct loop *loop; |
2337 loop_stride = loop_stride & will_be_nonconstant; | 2327 loop_stride = loop_stride & will_be_nonconstant; |
2338 } | 2328 } |
2339 } | 2329 } |
2340 free (body); | 2330 free (body); |
2341 } | 2331 } |
2342 set_hint_predicate (&ipa_fn_summaries->get (node)->loop_iterations, | 2332 ipa_fn_summary *s = ipa_fn_summaries->get (node); |
2343 loop_iterations); | 2333 set_hint_predicate (&s->loop_iterations, loop_iterations); |
2344 set_hint_predicate (&ipa_fn_summaries->get (node)->loop_stride, | 2334 set_hint_predicate (&s->loop_stride, loop_stride); |
2345 loop_stride); | |
2346 scev_finalize (); | 2335 scev_finalize (); |
2347 } | 2336 } |
2348 FOR_ALL_BB_FN (bb, my_function) | 2337 FOR_ALL_BB_FN (bb, my_function) |
2349 { | 2338 { |
2350 edge e; | 2339 edge e; |
2358 if (e->aux) | 2347 if (e->aux) |
2359 edge_predicate_pool.remove ((predicate *) e->aux); | 2348 edge_predicate_pool.remove ((predicate *) e->aux); |
2360 e->aux = NULL; | 2349 e->aux = NULL; |
2361 } | 2350 } |
2362 } | 2351 } |
2363 ipa_fn_summaries->get (node)->time = time; | 2352 ipa_fn_summary *s = ipa_fn_summaries->get (node); |
2364 ipa_fn_summaries->get (node)->self_size = size; | 2353 s->time = time; |
2354 s->self_size = size; | |
2365 nonconstant_names.release (); | 2355 nonconstant_names.release (); |
2366 ipa_release_body_info (&fbi); | 2356 ipa_release_body_info (&fbi); |
2367 if (opt_for_fn (node->decl, optimize)) | 2357 if (opt_for_fn (node->decl, optimize)) |
2368 { | 2358 { |
2369 if (!early) | 2359 if (!early) |
2393 gcc_assert (!node->global.inlined_to); | 2383 gcc_assert (!node->global.inlined_to); |
2394 | 2384 |
2395 if (!ipa_fn_summaries) | 2385 if (!ipa_fn_summaries) |
2396 ipa_fn_summary_alloc (); | 2386 ipa_fn_summary_alloc (); |
2397 | 2387 |
2398 info = ipa_fn_summaries->get (node); | 2388 /* Create a new ipa_fn_summary. */ |
2399 info->reset (node); | 2389 ((ipa_fn_summary_t *)ipa_fn_summaries)->remove_callees (node); |
2390 ipa_fn_summaries->remove (node); | |
2391 info = ipa_fn_summaries->get_create (node); | |
2400 | 2392 |
2401 /* Estimate the stack size for the function if we're optimizing. */ | 2393 /* Estimate the stack size for the function if we're optimizing. */ |
2402 self_stack_size = optimize && !node->thunk.thunk_p | 2394 self_stack_size = optimize && !node->thunk.thunk_p |
2403 ? estimated_stack_frame_size (node) : 0; | 2395 ? estimated_stack_frame_size (node) : 0; |
2404 info->estimated_self_stack_size = self_stack_size; | 2396 info->estimated_self_stack_size = self_stack_size; |
2405 info->estimated_stack_size = self_stack_size; | 2397 info->estimated_stack_size = self_stack_size; |
2406 info->stack_frame_offset = 0; | 2398 info->stack_frame_offset = 0; |
2407 | 2399 |
2408 if (node->thunk.thunk_p) | 2400 if (node->thunk.thunk_p) |
2409 { | 2401 { |
2410 struct ipa_call_summary *es = ipa_call_summaries->get (node->callees); | 2402 ipa_call_summary *es = ipa_call_summaries->get_create (node->callees); |
2411 predicate t = true; | 2403 predicate t = true; |
2412 | 2404 |
2413 node->local.can_change_signature = false; | 2405 node->local.can_change_signature = false; |
2414 es->call_stmt_size = eni_size_weights.call_cost; | 2406 es->call_stmt_size = eni_size_weights.call_cost; |
2415 es->call_stmt_time = eni_time_weights.call_cost; | 2407 es->call_stmt_time = eni_time_weights.call_cost; |
2422 if (node->thunk.add_pointer_bounds_args) | 2414 if (node->thunk.add_pointer_bounds_args) |
2423 { | 2415 { |
2424 info->inlinable = false; | 2416 info->inlinable = false; |
2425 node->callees->inline_failed = CIF_CHKP; | 2417 node->callees->inline_failed = CIF_CHKP; |
2426 } | 2418 } |
2419 else if (stdarg_p (TREE_TYPE (node->decl))) | |
2420 { | |
2421 info->inlinable = false; | |
2422 node->callees->inline_failed = CIF_VARIADIC_THUNK; | |
2423 } | |
2427 else | 2424 else |
2428 info->inlinable = true; | 2425 info->inlinable = true; |
2429 } | 2426 } |
2430 else | 2427 else |
2431 { | 2428 { |
2438 DECL_ATTRIBUTES (node->decl))) | 2435 DECL_ATTRIBUTES (node->decl))) |
2439 info->inlinable = false; | 2436 info->inlinable = false; |
2440 else | 2437 else |
2441 info->inlinable = tree_inlinable_function_p (node->decl); | 2438 info->inlinable = tree_inlinable_function_p (node->decl); |
2442 | 2439 |
2443 info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun); | |
2444 | |
2445 /* Type attributes can use parameter indices to describe them. */ | 2440 /* Type attributes can use parameter indices to describe them. */ |
2446 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) | 2441 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)) |
2442 /* Likewise for #pragma omp declare simd functions or functions | |
2443 with simd attribute. */ | |
2444 || lookup_attribute ("omp declare simd", | |
2445 DECL_ATTRIBUTES (node->decl))) | |
2447 node->local.can_change_signature = false; | 2446 node->local.can_change_signature = false; |
2448 else | 2447 else |
2449 { | 2448 { |
2450 /* Otherwise, inlinable functions always can change signature. */ | 2449 /* Otherwise, inlinable functions always can change signature. */ |
2451 if (info->inlinable) | 2450 if (info->inlinable) |
2454 { | 2453 { |
2455 /* Functions calling builtin_apply can not change signature. */ | 2454 /* Functions calling builtin_apply can not change signature. */ |
2456 for (e = node->callees; e; e = e->next_callee) | 2455 for (e = node->callees; e; e = e->next_callee) |
2457 { | 2456 { |
2458 tree cdecl = e->callee->decl; | 2457 tree cdecl = e->callee->decl; |
2459 if (DECL_BUILT_IN (cdecl) | 2458 if (fndecl_built_in_p (cdecl, BUILT_IN_APPLY_ARGS) |
2460 && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL | 2459 || fndecl_built_in_p (cdecl, BUILT_IN_VA_START)) |
2461 && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS | |
2462 || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START)) | |
2463 break; | 2460 break; |
2464 } | 2461 } |
2465 node->local.can_change_signature = !e; | 2462 node->local.can_change_signature = !e; |
2466 } | 2463 } |
2467 } | 2464 } |
2575 cur_size = call_size * ipa_fn_summary::size_scale; | 2572 cur_size = call_size * ipa_fn_summary::size_scale; |
2576 *size += cur_size; | 2573 *size += cur_size; |
2577 if (min_size) | 2574 if (min_size) |
2578 *min_size += cur_size; | 2575 *min_size += cur_size; |
2579 if (prob == REG_BR_PROB_BASE) | 2576 if (prob == REG_BR_PROB_BASE) |
2580 *time += ((sreal)(call_time * e->frequency)) / CGRAPH_FREQ_BASE; | 2577 *time += ((sreal)call_time) * e->sreal_frequency (); |
2581 else | 2578 else |
2582 *time += ((sreal)call_time) * (prob * e->frequency) | 2579 *time += ((sreal)call_time * prob) * e->sreal_frequency (); |
2583 / (CGRAPH_FREQ_BASE * REG_BR_PROB_BASE); | |
2584 } | 2580 } |
2585 | 2581 |
2586 | 2582 |
2587 | 2583 |
2588 /* Increase SIZE, MIN_SIZE and TIME for size and time needed to handle all | 2584 /* Increase SIZE, MIN_SIZE and TIME for size and time needed to handle all |
2599 vec<ipa_agg_jump_function_p> known_aggs) | 2595 vec<ipa_agg_jump_function_p> known_aggs) |
2600 { | 2596 { |
2601 struct cgraph_edge *e; | 2597 struct cgraph_edge *e; |
2602 for (e = node->callees; e; e = e->next_callee) | 2598 for (e = node->callees; e; e = e->next_callee) |
2603 { | 2599 { |
2604 struct ipa_call_summary *es = ipa_call_summaries->get (e); | 2600 struct ipa_call_summary *es = ipa_call_summaries->get_create (e); |
2605 | 2601 |
2606 /* Do not care about zero sized builtins. */ | 2602 /* Do not care about zero sized builtins. */ |
2607 if (e->inline_failed && !es->call_stmt_size) | 2603 if (e->inline_failed && !es->call_stmt_size) |
2608 { | 2604 { |
2609 gcc_checking_assert (!es->call_stmt_time); | 2605 gcc_checking_assert (!es->call_stmt_time); |
2630 known_aggs); | 2626 known_aggs); |
2631 } | 2627 } |
2632 } | 2628 } |
2633 for (e = node->indirect_calls; e; e = e->next_callee) | 2629 for (e = node->indirect_calls; e; e = e->next_callee) |
2634 { | 2630 { |
2635 struct ipa_call_summary *es = ipa_call_summaries->get (e); | 2631 struct ipa_call_summary *es = ipa_call_summaries->get_create (e); |
2636 if (!es->predicate | 2632 if (!es->predicate |
2637 || es->predicate->evaluate (possible_truths)) | 2633 || es->predicate->evaluate (possible_truths)) |
2638 estimate_edge_size_and_time (e, size, | 2634 estimate_edge_size_and_time (e, size, |
2639 es->predicate ? NULL : min_size, | 2635 es->predicate ? NULL : min_size, |
2640 time, REG_BR_PROB_BASE, | 2636 time, REG_BR_PROB_BASE, |
2665 sreal *ret_nonspecialized_time, | 2661 sreal *ret_nonspecialized_time, |
2666 ipa_hints *ret_hints, | 2662 ipa_hints *ret_hints, |
2667 vec<inline_param_summary> | 2663 vec<inline_param_summary> |
2668 inline_param_summary) | 2664 inline_param_summary) |
2669 { | 2665 { |
2670 struct ipa_fn_summary *info = ipa_fn_summaries->get (node); | 2666 struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node); |
2671 size_time_entry *e; | 2667 size_time_entry *e; |
2672 int size = 0; | 2668 int size = 0; |
2673 sreal time = 0; | 2669 sreal time = 0; |
2674 int min_size = 0; | 2670 int min_size = 0; |
2675 ipa_hints hints = 0; | 2671 ipa_hints hints = 0; |
2744 min_size = (*info->size_time_table)[0].size; | 2740 min_size = (*info->size_time_table)[0].size; |
2745 gcc_checking_assert (size >= 0); | 2741 gcc_checking_assert (size >= 0); |
2746 gcc_checking_assert (time >= 0); | 2742 gcc_checking_assert (time >= 0); |
2747 /* nonspecialized_time should be always bigger than specialized time. | 2743 /* nonspecialized_time should be always bigger than specialized time. |
2748 Roundoff issues however may get into the way. */ | 2744 Roundoff issues however may get into the way. */ |
2749 gcc_checking_assert ((nonspecialized_time - time) >= -1); | 2745 gcc_checking_assert ((nonspecialized_time - time * 99 / 100) >= -1); |
2750 | 2746 |
2751 /* Roundoff issues may make specialized time bigger than nonspecialized | 2747 /* Roundoff issues may make specialized time bigger than nonspecialized |
2752 time. We do not really want that to happen because some heurstics | 2748 time. We do not really want that to happen because some heurstics |
2753 may get confused by seeing negative speedups. */ | 2749 may get confused by seeing negative speedups. */ |
2754 if (time > nonspecialized_time) | 2750 if (time > nonspecialized_time) |
2819 | 2815 |
2820 static void | 2816 static void |
2821 inline_update_callee_summaries (struct cgraph_node *node, int depth) | 2817 inline_update_callee_summaries (struct cgraph_node *node, int depth) |
2822 { | 2818 { |
2823 struct cgraph_edge *e; | 2819 struct cgraph_edge *e; |
2824 struct ipa_fn_summary *callee_info = ipa_fn_summaries->get (node); | 2820 ipa_fn_summary *callee_info = ipa_fn_summaries->get (node); |
2825 struct ipa_fn_summary *caller_info = ipa_fn_summaries->get (node->callers->caller); | 2821 ipa_fn_summary *caller_info = ipa_fn_summaries->get (node->callers->caller); |
2826 HOST_WIDE_INT peak; | 2822 HOST_WIDE_INT peak; |
2827 | 2823 |
2828 callee_info->stack_frame_offset | 2824 callee_info->stack_frame_offset |
2829 = caller_info->stack_frame_offset | 2825 = caller_info->stack_frame_offset |
2830 + caller_info->estimated_self_stack_size; | 2826 + caller_info->estimated_self_stack_size; |
2831 peak = callee_info->stack_frame_offset | 2827 peak = callee_info->stack_frame_offset |
2832 + callee_info->estimated_self_stack_size; | 2828 + callee_info->estimated_self_stack_size; |
2833 if (ipa_fn_summaries->get (node->global.inlined_to)->estimated_stack_size < peak) | 2829 |
2834 ipa_fn_summaries->get (node->global.inlined_to)->estimated_stack_size = peak; | 2830 ipa_fn_summary *s = ipa_fn_summaries->get (node->global.inlined_to); |
2831 if (s->estimated_stack_size < peak) | |
2832 s->estimated_stack_size = peak; | |
2835 ipa_propagate_frequency (node); | 2833 ipa_propagate_frequency (node); |
2836 for (e = node->callees; e; e = e->next_callee) | 2834 for (e = node->callees; e; e = e->next_callee) |
2837 { | 2835 { |
2838 if (!e->inline_failed) | 2836 if (!e->inline_failed) |
2839 inline_update_callee_summaries (e->callee, depth); | 2837 inline_update_callee_summaries (e->callee, depth); |
2980 /* We inlined EDGE. Update summary of the function we inlined into. */ | 2978 /* We inlined EDGE. Update summary of the function we inlined into. */ |
2981 | 2979 |
2982 void | 2980 void |
2983 ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) | 2981 ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) |
2984 { | 2982 { |
2985 struct ipa_fn_summary *callee_info = ipa_fn_summaries->get (edge->callee); | 2983 ipa_fn_summary *callee_info = ipa_fn_summaries->get (edge->callee); |
2986 struct cgraph_node *to = (edge->caller->global.inlined_to | 2984 struct cgraph_node *to = (edge->caller->global.inlined_to |
2987 ? edge->caller->global.inlined_to : edge->caller); | 2985 ? edge->caller->global.inlined_to : edge->caller); |
2988 struct ipa_fn_summary *info = ipa_fn_summaries->get (to); | 2986 struct ipa_fn_summary *info = ipa_fn_summaries->get (to); |
2989 clause_t clause = 0; /* not_inline is known to be false. */ | 2987 clause_t clause = 0; /* not_inline is known to be false. */ |
2990 size_time_entry *e; | 2988 size_time_entry *e; |
3055 (info, callee_info, operand_map, | 3053 (info, callee_info, operand_map, |
3056 offset_map, clause, | 3054 offset_map, clause, |
3057 toplev_predicate); | 3055 toplev_predicate); |
3058 if (p != false && nonconstp != false) | 3056 if (p != false && nonconstp != false) |
3059 { | 3057 { |
3060 sreal add_time = ((sreal)e->time * edge->frequency) / CGRAPH_FREQ_BASE; | 3058 sreal add_time = ((sreal)e->time * edge->sreal_frequency ()); |
3061 int prob = e->nonconst_predicate.probability (callee_info->conds, | 3059 int prob = e->nonconst_predicate.probability (callee_info->conds, |
3062 clause, es->param); | 3060 clause, es->param); |
3063 add_time = add_time * prob / REG_BR_PROB_BASE; | 3061 add_time = add_time * prob / REG_BR_PROB_BASE; |
3064 if (prob != REG_BR_PROB_BASE | 3062 if (prob != REG_BR_PROB_BASE |
3065 && dump_file && (dump_flags & TDF_DETAILS)) | 3063 && dump_file && (dump_flags & TDF_DETAILS)) |
3080 operand_map, offset_map, clause, &toplev_predicate); | 3078 operand_map, offset_map, clause, &toplev_predicate); |
3081 remap_hint_predicate (info, callee_info, | 3079 remap_hint_predicate (info, callee_info, |
3082 &callee_info->array_index, | 3080 &callee_info->array_index, |
3083 operand_map, offset_map, clause, &toplev_predicate); | 3081 operand_map, offset_map, clause, &toplev_predicate); |
3084 | 3082 |
3085 inline_update_callee_summaries (edge->callee, | 3083 ipa_call_summary *s = ipa_call_summaries->get (edge); |
3086 ipa_call_summaries->get (edge)->loop_depth); | 3084 inline_update_callee_summaries (edge->callee, s->loop_depth); |
3087 | 3085 |
3088 /* We do not maintain predicates of inlined edges, free it. */ | 3086 /* We do not maintain predicates of inlined edges, free it. */ |
3089 edge_set_predicate (edge, &true_p); | 3087 edge_set_predicate (edge, &true_p); |
3090 /* Similarly remove param summaries. */ | 3088 /* Similarly remove param summaries. */ |
3091 es->param.release (); | 3089 es->param.release (); |
3097 and time. Recompute it. */ | 3095 and time. Recompute it. */ |
3098 | 3096 |
3099 void | 3097 void |
3100 ipa_update_overall_fn_summary (struct cgraph_node *node) | 3098 ipa_update_overall_fn_summary (struct cgraph_node *node) |
3101 { | 3099 { |
3102 struct ipa_fn_summary *info = ipa_fn_summaries->get (node); | 3100 struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node); |
3103 size_time_entry *e; | 3101 size_time_entry *e; |
3104 int i; | 3102 int i; |
3105 | 3103 |
3106 info->size = 0; | 3104 info->size = 0; |
3107 info->time = 0; | 3105 info->time = 0; |
3195 /* Write inline summary for edge E to OB. */ | 3193 /* Write inline summary for edge E to OB. */ |
3196 | 3194 |
3197 static void | 3195 static void |
3198 read_ipa_call_summary (struct lto_input_block *ib, struct cgraph_edge *e) | 3196 read_ipa_call_summary (struct lto_input_block *ib, struct cgraph_edge *e) |
3199 { | 3197 { |
3200 struct ipa_call_summary *es = ipa_call_summaries->get (e); | 3198 struct ipa_call_summary *es = ipa_call_summaries->get_create (e); |
3201 predicate p; | 3199 predicate p; |
3202 int length, i; | 3200 int length, i; |
3203 | 3201 |
3204 es->call_stmt_size = streamer_read_uhwi (ib); | 3202 es->call_stmt_size = streamer_read_uhwi (ib); |
3205 es->call_stmt_time = streamer_read_uhwi (ib); | 3203 es->call_stmt_time = streamer_read_uhwi (ib); |
3206 es->loop_depth = streamer_read_uhwi (ib); | 3204 es->loop_depth = streamer_read_uhwi (ib); |
3205 | |
3206 bitpack_d bp = streamer_read_bitpack (ib); | |
3207 es->is_return_callee_uncaptured = bp_unpack_value (&bp, 1); | |
3208 | |
3207 p.stream_in (ib); | 3209 p.stream_in (ib); |
3208 edge_set_predicate (e, &p); | 3210 edge_set_predicate (e, &p); |
3209 length = streamer_read_uhwi (ib); | 3211 length = streamer_read_uhwi (ib); |
3210 if (length) | 3212 if (length) |
3211 { | 3213 { |
3250 | 3252 |
3251 index = streamer_read_uhwi (&ib); | 3253 index = streamer_read_uhwi (&ib); |
3252 encoder = file_data->symtab_node_encoder; | 3254 encoder = file_data->symtab_node_encoder; |
3253 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder, | 3255 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder, |
3254 index)); | 3256 index)); |
3255 info = ipa_fn_summaries->get (node); | 3257 info = ipa_fn_summaries->get_create (node); |
3256 | 3258 |
3257 info->estimated_stack_size | 3259 info->estimated_stack_size |
3258 = info->estimated_self_stack_size = streamer_read_uhwi (&ib); | 3260 = info->estimated_self_stack_size = streamer_read_uhwi (&ib); |
3259 info->size = info->self_size = streamer_read_uhwi (&ib); | 3261 info->size = info->self_size = streamer_read_uhwi (&ib); |
3260 info->time = sreal::stream_in (&ib); | 3262 info->time = sreal::stream_in (&ib); |
3261 | 3263 |
3262 bp = streamer_read_bitpack (&ib); | 3264 bp = streamer_read_bitpack (&ib); |
3263 info->inlinable = bp_unpack_value (&bp, 1); | 3265 info->inlinable = bp_unpack_value (&bp, 1); |
3264 info->contains_cilk_spawn = bp_unpack_value (&bp, 1); | |
3265 info->fp_expressions = bp_unpack_value (&bp, 1); | 3266 info->fp_expressions = bp_unpack_value (&bp, 1); |
3266 | 3267 |
3267 count2 = streamer_read_uhwi (&ib); | 3268 count2 = streamer_read_uhwi (&ib); |
3268 gcc_assert (!info->conds); | 3269 gcc_assert (!info->conds); |
3269 for (j = 0; j < count2; j++) | 3270 for (j = 0; j < count2; j++) |
3358 int i; | 3359 int i; |
3359 | 3360 |
3360 streamer_write_uhwi (ob, es->call_stmt_size); | 3361 streamer_write_uhwi (ob, es->call_stmt_size); |
3361 streamer_write_uhwi (ob, es->call_stmt_time); | 3362 streamer_write_uhwi (ob, es->call_stmt_time); |
3362 streamer_write_uhwi (ob, es->loop_depth); | 3363 streamer_write_uhwi (ob, es->loop_depth); |
3364 | |
3365 bitpack_d bp = bitpack_create (ob->main_stream); | |
3366 bp_pack_value (&bp, es->is_return_callee_uncaptured, 1); | |
3367 streamer_write_bitpack (&bp); | |
3368 | |
3363 if (es->predicate) | 3369 if (es->predicate) |
3364 es->predicate->stream_out (ob); | 3370 es->predicate->stream_out (ob); |
3365 else | 3371 else |
3366 streamer_write_uhwi (ob, 0); | 3372 streamer_write_uhwi (ob, 0); |
3367 streamer_write_uhwi (ob, es->param.length ()); | 3373 streamer_write_uhwi (ob, es->param.length ()); |
3408 streamer_write_hwi (ob, info->estimated_self_stack_size); | 3414 streamer_write_hwi (ob, info->estimated_self_stack_size); |
3409 streamer_write_hwi (ob, info->self_size); | 3415 streamer_write_hwi (ob, info->self_size); |
3410 info->time.stream_out (ob); | 3416 info->time.stream_out (ob); |
3411 bp = bitpack_create (ob->main_stream); | 3417 bp = bitpack_create (ob->main_stream); |
3412 bp_pack_value (&bp, info->inlinable, 1); | 3418 bp_pack_value (&bp, info->inlinable, 1); |
3413 bp_pack_value (&bp, info->contains_cilk_spawn, 1); | 3419 bp_pack_value (&bp, false, 1); |
3414 bp_pack_value (&bp, info->fp_expressions, 1); | 3420 bp_pack_value (&bp, info->fp_expressions, 1); |
3415 streamer_write_bitpack (&bp); | 3421 streamer_write_bitpack (&bp); |
3416 streamer_write_uhwi (ob, vec_safe_length (info->conds)); | 3422 streamer_write_uhwi (ob, vec_safe_length (info->conds)); |
3417 for (i = 0; vec_safe_iterate (info->conds, i, &c); i++) | 3423 for (i = 0; vec_safe_iterate (info->conds, i, &c); i++) |
3418 { | 3424 { |
3470 struct cgraph_node *node; | 3476 struct cgraph_node *node; |
3471 if (!ipa_call_summaries) | 3477 if (!ipa_call_summaries) |
3472 return; | 3478 return; |
3473 FOR_EACH_DEFINED_FUNCTION (node) | 3479 FOR_EACH_DEFINED_FUNCTION (node) |
3474 if (!node->alias) | 3480 if (!node->alias) |
3475 ipa_fn_summaries->get (node)->reset (node); | 3481 ipa_fn_summaries->remove (node); |
3476 ipa_fn_summaries->release (); | 3482 ipa_fn_summaries->release (); |
3477 ipa_fn_summaries = NULL; | 3483 ipa_fn_summaries = NULL; |
3478 ipa_call_summaries->release (); | 3484 ipa_call_summaries->release (); |
3479 delete ipa_call_summaries; | 3485 delete ipa_call_summaries; |
3480 ipa_call_summaries = NULL; | 3486 ipa_call_summaries = NULL; |
3533 TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */ | 3539 TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */ |
3534 0, /* properties_required */ | 3540 0, /* properties_required */ |
3535 0, /* properties_provided */ | 3541 0, /* properties_provided */ |
3536 0, /* properties_destroyed */ | 3542 0, /* properties_destroyed */ |
3537 0, /* todo_flags_start */ | 3543 0, /* todo_flags_start */ |
3538 /* Early optimizations may make function unreachable. We can not | 3544 0, /* todo_flags_finish */ |
3539 remove unreachable functions as part of the ealry opts pass because | |
3540 TODOs are run before subpasses. Do it here. */ | |
3541 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */ | |
3542 }; | 3545 }; |
3543 | 3546 |
3544 class pass_ipa_free_fn_summary : public simple_ipa_opt_pass | 3547 class pass_ipa_free_fn_summary : public simple_ipa_opt_pass |
3545 { | 3548 { |
3546 public: | 3549 public: |
3547 pass_ipa_free_fn_summary (gcc::context *ctxt) | 3550 pass_ipa_free_fn_summary (gcc::context *ctxt) |
3548 : simple_ipa_opt_pass (pass_data_ipa_free_fn_summary, ctxt) | 3551 : simple_ipa_opt_pass (pass_data_ipa_free_fn_summary, ctxt), |
3552 small_p (false) | |
3549 {} | 3553 {} |
3550 | 3554 |
3551 /* opt_pass methods: */ | 3555 /* opt_pass methods: */ |
3556 opt_pass *clone () { return new pass_ipa_free_fn_summary (m_ctxt); } | |
3557 void set_pass_param (unsigned int n, bool param) | |
3558 { | |
3559 gcc_assert (n == 0); | |
3560 small_p = param; | |
3561 } | |
3562 virtual bool gate (function *) { return small_p || !flag_wpa; } | |
3552 virtual unsigned int execute (function *) | 3563 virtual unsigned int execute (function *) |
3553 { | 3564 { |
3554 ipa_free_fn_summary (); | 3565 ipa_free_fn_summary (); |
3555 return 0; | 3566 /* Early optimizations may make function unreachable. We can not |
3556 } | 3567 remove unreachable functions as part of the early opts pass because |
3557 | 3568 TODOs are run before subpasses. Do it here. */ |
3569 return small_p ? TODO_remove_functions | TODO_dump_symtab : 0; | |
3570 } | |
3571 | |
3572 private: | |
3573 bool small_p; | |
3558 }; // class pass_ipa_free_fn_summary | 3574 }; // class pass_ipa_free_fn_summary |
3559 | 3575 |
3560 } // anon namespace | 3576 } // anon namespace |
3561 | 3577 |
3562 simple_ipa_opt_pass * | 3578 simple_ipa_opt_pass * |
3606 ipa_opt_pass_d * | 3622 ipa_opt_pass_d * |
3607 make_pass_ipa_fn_summary (gcc::context *ctxt) | 3623 make_pass_ipa_fn_summary (gcc::context *ctxt) |
3608 { | 3624 { |
3609 return new pass_ipa_fn_summary (ctxt); | 3625 return new pass_ipa_fn_summary (ctxt); |
3610 } | 3626 } |
3627 | |
3628 /* Reset all state within ipa-fnsummary.c so that we can rerun the compiler | |
3629 within the same process. For use by toplev::finalize. */ | |
3630 | |
3631 void | |
3632 ipa_fnsummary_c_finalize (void) | |
3633 { | |
3634 ipa_free_fn_summary (); | |
3635 } |