]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-inline.h
This patch rewrites the old VEC macro-based interface into a new one
[thirdparty/gcc.git] / gcc / ipa-inline.h
CommitLineData
99c67f24 1/* Inlining decision heuristics.
2 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Jan Hubicka
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
803a7988 22#include "ipa-prop.h"
23
a41f2a28 24/* Representation of inline parameters that do depend on context function is
25 inlined into (i.e. known constant values of function parameters.
26
27 Conditions that are interesting for function body are collected into CONDS
28 vector. They are of simple for function_param OP VAL, where VAL is
04ec15fa 29 IPA invariant. The conditions are then referred by predicates. */
a41f2a28 30
31typedef struct GTY(()) condition
32 {
a4f60e55 33 /* If agg_contents is set, this is the offset from which the used data was
34 loaded. */
35 HOST_WIDE_INT offset;
a41f2a28 36 tree val;
37 int operand_num;
a4f60e55 38 ENUM_BITFIELD(tree_code) code : 16;
39 /* Set if the used data were loaded from an aggregate parameter or from
40 data received by reference. */
41 unsigned agg_contents : 1;
42 /* If agg_contents is set, this differentiates between loads from data
43 passed by reference and by value. */
44 unsigned by_ref : 1;
a41f2a28 45 } condition;
46
be343a9c 47/* Inline hints are reasons why inline heuristics should preffer inlining given
48 function. They are represtented as bitmap of the following values. */
eb7c606e 49enum inline_hints_vals {
be343a9c 50 /* When inlining turns indirect call into a direct call,
51 it is good idea to do so. */
7c07aa3d 52 INLINE_HINT_indirect_call = 1,
be343a9c 53 /* Inlining may make loop iterations or loop stride known. It is good idea
54 to do so because it enables loop optimizatoins. */
3716ee8f 55 INLINE_HINT_loop_iterations = 2,
41d39f38 56 INLINE_HINT_loop_stride = 4,
be343a9c 57 /* Inlining withing same strongly connected component of callgraph is often
58 a loss due to increased stack frame usage and prologue setup costs. */
41d39f38 59 INLINE_HINT_same_scc = 8,
be343a9c 60 /* Inlining functions in strongly connected component is not such a great
61 win. */
3172b7bf 62 INLINE_HINT_in_scc = 16,
be343a9c 63 /* If function is declared inline by user, it may be good idea to inline
64 it. */
3172b7bf 65 INLINE_HINT_declared_inline = 32,
be343a9c 66 /* Programs are usually still organized for non-LTO compilation and thus
67 if functions are in different modules, inlining may not be so important.
68 */
69 INLINE_HINT_cross_module = 64,
70 /* If array indexes of loads/stores become known there may be room for
71 futher optimization. */
72 INLINE_HINT_array_index = 128
eb7c606e 73};
74typedef int inline_hints;
75
a41f2a28 76
f1f41a6c 77typedef vec<condition, va_gc> *conditions;
a41f2a28 78
79/* Representation of predicates i.e. formulas using conditions defined
80 above. Predicates are simple logical formulas in conjunctive-disjunctive
81 form.
82
83 Predicate is array of clauses terminated by 0. Every clause must be true
84 in order to make predicate true.
85 Clauses are represented as bitmaps of conditions. One of conditions
86 must be true in order for clause to be true. */
87
88#define MAX_CLAUSES 8
905aa3bd 89typedef unsigned int clause_t;
a41f2a28 90struct GTY(()) predicate
91{
92 clause_t clause[MAX_CLAUSES + 1];
93};
94
95/* Represnetation of function body size and time depending on the inline
96 context. We keep simple array of record, every containing of predicate
97 and time/size to account.
c7b2cc59 98
a41f2a28 99 We keep values scaled up, so fractional sizes and times can be
100 accounted. */
101#define INLINE_SIZE_SCALE 2
102#define INLINE_TIME_SCALE (CGRAPH_FREQ_BASE * 2)
103typedef struct GTY(()) size_time_entry
104{
105 struct predicate predicate;
106 int size;
107 int time;
108} size_time_entry;
a41f2a28 109
110/* Function inlining information. */
111struct GTY(()) inline_summary
c7b2cc59 112{
cbd7f5a0 113 /* Information about the function body itself. */
114
c7b2cc59 115 /* Estimated stack frame consumption by the function. */
116 HOST_WIDE_INT estimated_self_stack_size;
c7b2cc59 117 /* Size of the function body. */
118 int self_size;
a41f2a28 119 /* Time of the function body. */
c7b2cc59 120 int self_time;
cbd7f5a0 121
122 /* False when there something makes inlining impossible (such as va_arg). */
123 unsigned inlinable : 1;
cbd7f5a0 124
125 /* Information about function that will result after applying all the
126 inline decisions present in the callgraph. Generally kept up to
127 date only for functions that are not inline clones. */
128
129 /* Estimated stack frame consumption by the function. */
130 HOST_WIDE_INT estimated_stack_size;
131 /* Expected offset of the stack frame of inlined function. */
132 HOST_WIDE_INT stack_frame_offset;
133 /* Estimated size of the function after inlining. */
134 int time;
135 int size;
a41f2a28 136
0835ad03 137 /* Conditional size/time information. The summaries are being
138 merged during inlining. */
a41f2a28 139 conditions conds;
f1f41a6c 140 vec<size_time_entry, va_gc> *entry;
7c07aa3d 141
3716ee8f 142 /* Predicate on when some loop in the function becomes to have known
7c07aa3d 143 bounds. */
144 struct predicate * GTY((skip)) loop_iterations;
3716ee8f 145 /* Predicate on when some loop in the function becomes to have known
146 stride. */
147 struct predicate * GTY((skip)) loop_stride;
be343a9c 148 /* Predicate on when some array indexes become constants. */
149 struct predicate * GTY((skip)) array_index;
3172b7bf 150 /* Estimated growth for inlining all copies of the function before start
151 of small functions inlining.
152 This value will get out of date as the callers are duplicated, but
153 using up-to-date value in the badness metric mean a lot of extra
154 expenses. */
155 int growth;
41d39f38 156 /* Number of SCC on the beggining of inlining process. */
157 int scc_no;
c7b2cc59 158};
159
eb4ae064 160
c7b2cc59 161typedef struct inline_summary inline_summary_t;
f1f41a6c 162extern GTY(()) vec<inline_summary_t, va_gc> *inline_summary_vec;
a41f2a28 163
eb4ae064 164/* Information kept about parameter of call site. */
165struct inline_param_summary
166{
167 /* REG_BR_PROB_BASE based probability that parameter will change in between
168 two invocation of the calls.
169 I.e. loop invariant parameters
170 REG_BR_PROB_BASE/estimated_iterations and regular
171 parameters REG_BR_PROB_BASE.
172
173 Value 0 is reserved for compile time invariants. */
174 int change_prob;
175};
176typedef struct inline_param_summary inline_param_summary_t;
eb4ae064 177
0835ad03 178/* Information kept about callgraph edges. */
179struct inline_edge_summary
180{
181 /* Estimated size and time of the call statement. */
182 int call_stmt_size;
183 int call_stmt_time;
184 /* Depth of loop nest, 0 means no nesting. */
185 unsigned short int loop_depth;
6a18c0be 186 struct predicate *predicate;
eb4ae064 187 /* Array indexed by parameters.
188 0 means that parameter change all the time, REG_BR_PROB_BASE means
189 that parameter is constant. */
f1f41a6c 190 vec<inline_param_summary_t> param;
0835ad03 191};
192
193typedef struct inline_edge_summary inline_edge_summary_t;
f1f41a6c 194extern vec<inline_edge_summary_t> inline_edge_summary_vec;
0835ad03 195
a41f2a28 196typedef struct edge_growth_cache_entry
197{
198 int time, size;
eb7c606e 199 inline_hints hints;
a41f2a28 200} edge_growth_cache_entry;
a41f2a28 201
f1f41a6c 202extern vec<int> node_growth_cache;
203extern vec<edge_growth_cache_entry> edge_growth_cache;
c7b2cc59 204
8cbc43ff 205/* In ipa-inline-analysis.c */
c7b2cc59 206void debug_inline_summary (struct cgraph_node *);
207void dump_inline_summaries (FILE *f);
eb7c606e 208void dump_inline_summary (FILE *f, struct cgraph_node *node);
209void dump_inline_hints (FILE *f, inline_hints);
99c67f24 210void inline_generate_summary (void);
211void inline_read_summary (void);
eab36a5a 212void inline_write_summary (void);
99c67f24 213void inline_free_summary (void);
cbd7f5a0 214void initialize_inline_failed (struct cgraph_edge *);
99c67f24 215int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
216int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
93f713da 217void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
f1f41a6c 218 vec<tree>, vec<tree>,
219 vec<ipa_agg_jump_function_p>,
803a7988 220 int *, int *, inline_hints *);
a41f2a28 221int do_estimate_growth (struct cgraph_node *);
222void inline_merge_summary (struct cgraph_edge *edge);
6331b6fa 223void inline_update_overall_summary (struct cgraph_node *node);
6c2c7775 224int do_estimate_edge_size (struct cgraph_edge *edge);
a41f2a28 225int do_estimate_edge_time (struct cgraph_edge *edge);
eb7c606e 226inline_hints do_estimate_edge_hints (struct cgraph_edge *edge);
a41f2a28 227void initialize_growth_caches (void);
228void free_growth_caches (void);
229void compute_inline_parameters (struct cgraph_node *, bool);
99c67f24 230
8cbc43ff 231/* In ipa-inline-transform.c */
f1f41a6c 232bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool);
8cbc43ff 233unsigned int inline_transform (struct cgraph_node *);
234void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *);
235
236extern int ncalls_inlined;
237extern int nfunctions_inlined;
238
99c67f24 239static inline struct inline_summary *
240inline_summary (struct cgraph_node *node)
241{
f1f41a6c 242 return &(*inline_summary_vec)[node->uid];
99c67f24 243}
244
0835ad03 245static inline struct inline_edge_summary *
246inline_edge_summary (struct cgraph_edge *edge)
247{
f1f41a6c 248 return &inline_edge_summary_vec[edge->uid];
0835ad03 249}
a41f2a28 250
251/* Return estimated unit growth after inlning all calls to NODE.
252 Quick accesors to the inline growth caches.
253 For convenience we keep zero 0 as unknown. Because growth
254 can be both positive and negative, we simply increase positive
255 growths by 1. */
256static inline int
257estimate_growth (struct cgraph_node *node)
258{
259 int ret;
f1f41a6c 260 if ((int)node_growth_cache.length () <= node->uid
261 || !(ret = node_growth_cache[node->uid]))
a41f2a28 262 return do_estimate_growth (node);
263 return ret - (ret > 0);
264}
265
266
6c2c7775 267/* Return estimated size of the inline sequence of EDGE. */
99c67f24 268
269static inline int
6c2c7775 270estimate_edge_size (struct cgraph_edge *edge)
99c67f24 271{
a41f2a28 272 int ret;
f1f41a6c 273 if ((int)edge_growth_cache.length () <= edge->uid
274 || !(ret = edge_growth_cache[edge->uid].size))
6c2c7775 275 return do_estimate_edge_size (edge);
a41f2a28 276 return ret - (ret > 0);
277}
278
6c2c7775 279/* Return estimated callee growth after inlining EDGE. */
280
281static inline int
282estimate_edge_growth (struct cgraph_edge *edge)
283{
284#ifdef ENABLE_CHECKING
285 gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size);
286#endif
287 return (estimate_edge_size (edge)
288 - inline_edge_summary (edge)->call_stmt_size);
289}
a41f2a28 290
291/* Return estimated callee runtime increase after inlning
292 EDGE. */
293
294static inline int
295estimate_edge_time (struct cgraph_edge *edge)
296{
297 int ret;
f1f41a6c 298 if ((int)edge_growth_cache.length () <= edge->uid
299 || !(ret = edge_growth_cache[edge->uid].time))
a41f2a28 300 return do_estimate_edge_time (edge);
301 return ret - (ret > 0);
302}
303
304
eb7c606e 305/* Return estimated callee runtime increase after inlning
306 EDGE. */
307
308static inline inline_hints
309estimate_edge_hints (struct cgraph_edge *edge)
310{
311 inline_hints ret;
f1f41a6c 312 if ((int)edge_growth_cache.length () <= edge->uid
313 || !(ret = edge_growth_cache[edge->uid].hints))
6e300957 314 return do_estimate_edge_hints (edge);
eb7c606e 315 return ret - 1;
316}
317
318
a41f2a28 319/* Reset cached value for NODE. */
320
321static inline void
322reset_node_growth_cache (struct cgraph_node *node)
323{
f1f41a6c 324 if ((int)node_growth_cache.length () > node->uid)
325 node_growth_cache[node->uid] = 0;
a41f2a28 326}
327
328/* Reset cached value for EDGE. */
329
330static inline void
331reset_edge_growth_cache (struct cgraph_edge *edge)
332{
f1f41a6c 333 if ((int)edge_growth_cache.length () > edge->uid)
a41f2a28 334 {
eb7c606e 335 struct edge_growth_cache_entry zero = {0, 0, 0};
f1f41a6c 336 edge_growth_cache[edge->uid] = zero;
a41f2a28 337 }
99c67f24 338}