1 /* Inlining decision heuristics. 2 Copyright (C) 2003-2020 Free Software Foundation, Inc. 3 Contributed by Jan Hubicka 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #ifndef GCC_IPA_INLINE_H 22 #define GCC_IPA_INLINE_H 23 24 /* Data we cache about callgraph edges during inlining to avoid expensive 25 re-computations during the greedy algorithm. */ 26 class edge_growth_cache_entry 27 { 28 public: 29 sreal time, nonspec_time; 30 int size; 31 ipa_hints hints; 32 33 edge_growth_cache_entry() 34 : size (0), hints (0) {} 35 36 edge_growth_cache_entry(int64_t time, int64_t nonspec_time, 37 int size, ipa_hints hints) 38 : time (time), nonspec_time (nonspec_time), size (size), 39 hints (hints) {} 40 }; 41 42 extern fast_call_summary<edge_growth_cache_entry *, va_heap> *edge_growth_cache; 43 44 /* In ipa-inline-analysis.c */ 45 int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *); 46 int estimate_growth (struct cgraph_node *); 47 bool growth_positive_p (struct cgraph_node *, struct cgraph_edge *, int); 48 int do_estimate_edge_size (struct cgraph_edge *edge); 49 sreal do_estimate_edge_time (struct cgraph_edge *edge, sreal *nonspec_time = NULL); 50 ipa_hints do_estimate_edge_hints (struct cgraph_edge *edge); 51 void reset_node_cache (struct cgraph_node *node); 52 void initialize_growth_caches (); 53 void free_growth_caches (void); 54 55 /* In ipa-inline.c */ 56 unsigned int early_inliner (function *fun); 57 bool inline_account_function_p (struct cgraph_node *node); 58 59 60 /* In ipa-inline-transform.c */ 61 bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge *> *, int *, bool, 62 bool *callee_removed = NULL); 63 unsigned int inline_transform (struct cgraph_node *); 64 void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *); 65 66 extern int ncalls_inlined; 67 extern int nfunctions_inlined; 68 extern function_summary <tree *> *ipa_saved_clone_sources; 69 70 /* Return estimated size of the inline sequence of EDGE. */ 71 72 static inline int 73 estimate_edge_size (struct cgraph_edge *edge) 74 { 75 edge_growth_cache_entry *entry; 76 if (edge_growth_cache == NULL 77 || (entry = edge_growth_cache->get (edge)) == NULL 78 || entry->size == 0) 79 return do_estimate_edge_size (edge); 80 return entry->size - (entry->size > 0); 81 } 82 83 /* Return lower bound on estimated callee growth after inlining EDGE. */ 84 85 static inline int 86 estimate_min_edge_growth (struct cgraph_edge *edge) 87 { 88 ipa_call_summary *s = ipa_call_summaries->get (edge); 89 struct cgraph_node *callee = edge->callee->ultimate_alias_target (); 90 return (ipa_fn_summaries->get (callee)->min_size - s->call_stmt_size); 91 } 92 93 /* Return estimated callee growth after inlining EDGE. */ 94 95 static inline int 96 estimate_edge_growth (struct cgraph_edge *edge) 97 { 98 ipa_call_summary *s = ipa_call_summaries->get (edge); 99 gcc_checking_assert (s->call_stmt_size || !edge->callee->analyzed); 100 return (estimate_edge_size (edge) - s->call_stmt_size); 101 } 102 103 /* Return estimated callee runtime increase after inlining 104 EDGE. */ 105 106 static inline sreal 107 estimate_edge_time (struct cgraph_edge *edge, sreal *nonspec_time = NULL) 108 { 109 edge_growth_cache_entry *entry; 110 if (edge_growth_cache == NULL 111 || (entry = edge_growth_cache->get (edge)) == NULL 112 || entry->time == 0) 113 return do_estimate_edge_time (edge, nonspec_time); 114 if (nonspec_time) 115 *nonspec_time = edge_growth_cache->get (edge)->nonspec_time; 116 return entry->time; 117 } 118 119 120 /* Return estimated callee runtime increase after inlining 121 EDGE. */ 122 123 static inline ipa_hints 124 estimate_edge_hints (struct cgraph_edge *edge) 125 { 126 edge_growth_cache_entry *entry; 127 if (edge_growth_cache == NULL 128 || (entry = edge_growth_cache->get (edge)) == NULL 129 || entry->hints == 0) 130 return do_estimate_edge_hints (edge); 131 return entry->hints - 1; 132 } 133 134 #endif /* GCC_IPA_INLINE_H */ 135