comparison gcc/ipa-fnsummary.h @ 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 /* IPA function body analysis. 1 /* IPA function body analysis.
2 Copyright (C) 2003-2018 Free Software Foundation, Inc. 2 Copyright (C) 2003-2020 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
23 23
24 #include "sreal.h" 24 #include "sreal.h"
25 #include "ipa-predicate.h" 25 #include "ipa-predicate.h"
26 26
27 27
28 /* Hints are reasons why IPA heuristics should preffer specializing given 28 /* Hints are reasons why IPA heuristics should prefer specializing given
29 function. They are represtented as bitmap of the following values. */ 29 function. They are represented as bitmap of the following values. */
30 enum ipa_hints_vals { 30 enum ipa_hints_vals {
31 /* When specialization turns indirect call into a direct call, 31 /* When specialization turns indirect call into a direct call,
32 it is good idea to do so. */ 32 it is good idea to do so. */
33 INLINE_HINT_indirect_call = 1, 33 INLINE_HINT_indirect_call = 1,
34 /* Inlining may make loop iterations or loop stride known. It is good idea 34 /* Inlining may make loop iterations or loop stride known. It is good idea
35 to do so because it enables loop optimizatoins. */ 35 to do so because it enables loop optimizations. */
36 INLINE_HINT_loop_iterations = 2, 36 INLINE_HINT_loop_iterations = 2,
37 INLINE_HINT_loop_stride = 4, 37 INLINE_HINT_loop_stride = 4,
38 /* Inlining within same strongly connected component of callgraph is often 38 /* Inlining within same strongly connected component of callgraph is often
39 a loss due to increased stack frame usage and prologue setup costs. */ 39 a loss due to increased stack frame usage and prologue setup costs. */
40 INLINE_HINT_same_scc = 8, 40 INLINE_HINT_same_scc = 8,
46 INLINE_HINT_declared_inline = 32, 46 INLINE_HINT_declared_inline = 32,
47 /* Programs are usually still organized for non-LTO compilation and thus 47 /* Programs are usually still organized for non-LTO compilation and thus
48 if functions are in different modules, inlining may not be so important. 48 if functions are in different modules, inlining may not be so important.
49 Set by simple_edge_hints in ipa-inline-analysis.c. */ 49 Set by simple_edge_hints in ipa-inline-analysis.c. */
50 INLINE_HINT_cross_module = 64, 50 INLINE_HINT_cross_module = 64,
51 /* If array indexes of loads/stores become known there may be room for
52 further optimization. */
53 INLINE_HINT_array_index = 128,
54 /* We know that the callee is hot by profile. */ 51 /* We know that the callee is hot by profile. */
55 INLINE_HINT_known_hot = 256 52 INLINE_HINT_known_hot = 128
56 }; 53 };
57 54
58 typedef int ipa_hints; 55 typedef int ipa_hints;
59 56
60 /* Simple description of whether a memory load or a condition refers to a load 57 /* Simple description of whether a memory load or a condition refers to a load
70 }; 67 };
71 68
72 /* Representation of function body size and time depending on the call 69 /* Representation of function body size and time depending on the call
73 context. We keep simple array of record, every containing of predicate 70 context. We keep simple array of record, every containing of predicate
74 and time/size to account. */ 71 and time/size to account. */
75 struct GTY(()) size_time_entry 72 class GTY(()) size_time_entry
76 { 73 {
74 public:
77 /* Predicate for code to be executed. */ 75 /* Predicate for code to be executed. */
78 predicate exec_predicate; 76 predicate exec_predicate;
79 /* Predicate for value to be constant and optimized out in a specialized copy. 77 /* Predicate for value to be constant and optimized out in a specialized copy.
80 When deciding on specialization this makes it possible to see how much 78 When deciding on specialization this makes it possible to see how much
81 the executed code paths will simplify. */ 79 the executed code paths will simplify. */
82 predicate nonconst_predicate; 80 predicate nonconst_predicate;
83 int size; 81 int size;
84 sreal GTY((skip)) time; 82 sreal GTY((skip)) time;
85 }; 83 };
86 84
87 /* Function inlining information. */ 85 /* Summary about function and stack frame sizes. We keep this info
88 struct GTY(()) ipa_fn_summary 86 for inline clones and also for WPA streaming. For this reason this is not
89 { 87 part of ipa_fn_summary which exists only for offline functions. */
90 /* Keep all field empty so summary dumping works during its computation. 88 class ipa_size_summary
91 This is useful for debugging. */ 89 {
92 ipa_fn_summary () 90 public:
93 : estimated_self_stack_size (0), self_size (0), min_size (0),
94 inlinable (false), single_caller (false),
95 fp_expressions (false), estimated_stack_size (false),
96 stack_frame_offset (false), time (0), size (0), conds (NULL),
97 size_time_table (NULL), loop_iterations (NULL), loop_stride (NULL),
98 array_index (NULL), growth (0), scc_no (0)
99 {
100 }
101
102 /* Copy constructor. */
103 ipa_fn_summary (const ipa_fn_summary &s)
104 : estimated_self_stack_size (s.estimated_self_stack_size),
105 self_size (s.self_size), min_size (s.min_size),
106 inlinable (s.inlinable), single_caller (s.single_caller),
107 fp_expressions (s.fp_expressions),
108 estimated_stack_size (s.estimated_stack_size),
109 stack_frame_offset (s.stack_frame_offset), time (s.time), size (s.size),
110 conds (s.conds), size_time_table (s.size_time_table),
111 loop_iterations (s.loop_iterations), loop_stride (s.loop_stride),
112 array_index (s.array_index), growth (s.growth), scc_no (s.scc_no)
113 {}
114
115 /* Default constructor. */
116 ~ipa_fn_summary ();
117
118 /* Information about the function body itself. */
119
120 /* Estimated stack frame consumption by the function. */ 91 /* Estimated stack frame consumption by the function. */
121 HOST_WIDE_INT estimated_self_stack_size; 92 HOST_WIDE_INT estimated_self_stack_size;
122 /* Size of the function body. */ 93 /* Size of the function body. */
123 int self_size; 94 int self_size;
95 /* Estimated size of the function after inlining. */
96 int size;
97
98 ipa_size_summary ()
99 : estimated_self_stack_size (0), self_size (0), size (0)
100 {
101 }
102 };
103
104 /* Function inlining information. */
105 class GTY(()) ipa_fn_summary
106 {
107 public:
108 /* Keep all field empty so summary dumping works during its computation.
109 This is useful for debugging. */
110 ipa_fn_summary ()
111 : min_size (0),
112 inlinable (false), single_caller (false),
113 fp_expressions (false), estimated_stack_size (false),
114 time (0), conds (NULL),
115 size_time_table (NULL), call_size_time_table (NULL), loop_iterations (NULL),
116 loop_stride (NULL), growth (0), scc_no (0)
117 {
118 }
119
120 /* Copy constructor. */
121 ipa_fn_summary (const ipa_fn_summary &s)
122 : min_size (s.min_size),
123 inlinable (s.inlinable), single_caller (s.single_caller),
124 fp_expressions (s.fp_expressions),
125 estimated_stack_size (s.estimated_stack_size),
126 time (s.time), conds (s.conds), size_time_table (s.size_time_table),
127 call_size_time_table (NULL),
128 loop_iterations (s.loop_iterations), loop_stride (s.loop_stride),
129 growth (s.growth), scc_no (s.scc_no)
130 {}
131
132 /* Default constructor. */
133 ~ipa_fn_summary ();
134
135 /* Information about the function body itself. */
136
124 /* Minimal size increase after inlining. */ 137 /* Minimal size increase after inlining. */
125 int min_size; 138 int min_size;
126 139
127 /* False when there something makes inlining impossible (such as va_arg). */ 140 /* False when there something makes inlining impossible (such as va_arg). */
128 unsigned inlinable : 1; 141 unsigned inlinable : 1;
136 inline decisions present in the callgraph. Generally kept up to 149 inline decisions present in the callgraph. Generally kept up to
137 date only for functions that are not inline clones. */ 150 date only for functions that are not inline clones. */
138 151
139 /* Estimated stack frame consumption by the function. */ 152 /* Estimated stack frame consumption by the function. */
140 HOST_WIDE_INT estimated_stack_size; 153 HOST_WIDE_INT estimated_stack_size;
141 /* Expected offset of the stack frame of function. */ 154 /* Estimated runtime of function after inlining. */
142 HOST_WIDE_INT stack_frame_offset;
143 /* Estimated size of the function after inlining. */
144 sreal GTY((skip)) time; 155 sreal GTY((skip)) time;
145 int size;
146 156
147 /* Conditional size/time information. The summaries are being 157 /* Conditional size/time information. The summaries are being
148 merged during inlining. */ 158 merged during inlining. */
149 conditions conds; 159 conditions conds;
160 /* Normal code is accounted in size_time_table, while calls are
161 accounted in call_size_time_table. This is because calls
162 are often adjusted by IPA optimizations and thus this summary
163 is generated from call summary information when needed. */
150 vec<size_time_entry, va_gc> *size_time_table; 164 vec<size_time_entry, va_gc> *size_time_table;
165 vec<size_time_entry, va_gc> *call_size_time_table;
151 166
152 /* Predicate on when some loop in the function becomes to have known 167 /* Predicate on when some loop in the function becomes to have known
153 bounds. */ 168 bounds. */
154 predicate * GTY((skip)) loop_iterations; 169 predicate * GTY((skip)) loop_iterations;
155 /* Predicate on when some loop in the function becomes to have known 170 /* Predicate on when some loop in the function becomes to have known
156 stride. */ 171 stride. */
157 predicate * GTY((skip)) loop_stride; 172 predicate * GTY((skip)) loop_stride;
158 /* Predicate on when some array indexes become constants. */
159 predicate * GTY((skip)) array_index;
160 /* Estimated growth for inlining all copies of the function before start 173 /* Estimated growth for inlining all copies of the function before start
161 of small functions inlining. 174 of small functions inlining.
162 This value will get out of date as the callers are duplicated, but 175 This value will get out of date as the callers are duplicated, but
163 using up-to-date value in the badness metric mean a lot of extra 176 using up-to-date value in the badness metric mean a lot of extra
164 expenses. */ 177 expenses. */
165 int growth; 178 int growth;
166 /* Number of SCC on the beginning of inlining process. */ 179 /* Number of SCC on the beginning of inlining process. */
167 int scc_no; 180 int scc_no;
168 181
169 /* Record time and size under given predicates. */ 182 /* Record time and size under given predicates. */
170 void account_size_time (int, sreal, const predicate &, const predicate &); 183 void account_size_time (int, sreal, const predicate &, const predicate &,
184 bool call = false);
171 185
172 /* We keep values scaled up, so fractional sizes can be accounted. */ 186 /* We keep values scaled up, so fractional sizes can be accounted. */
173 static const int size_scale = 2; 187 static const int size_scale = 2;
174 }; 188 /* Maximal size of size_time_table before we start to be conservative. */
175 189 static const int max_size_time_table_size = 256;
176 class GTY((user)) ipa_fn_summary_t: public function_summary <ipa_fn_summary *> 190 };
177 { 191
178 public: 192 class GTY((user)) ipa_fn_summary_t:
179 ipa_fn_summary_t (symbol_table *symtab, bool ggc): 193 public fast_function_summary <ipa_fn_summary *, va_gc>
180 function_summary <ipa_fn_summary *> (symtab, ggc) {} 194 {
195 public:
196 ipa_fn_summary_t (symbol_table *symtab):
197 fast_function_summary <ipa_fn_summary *, va_gc> (symtab) {}
181 198
182 static ipa_fn_summary_t *create_ggc (symbol_table *symtab) 199 static ipa_fn_summary_t *create_ggc (symbol_table *symtab)
183 { 200 {
184 struct ipa_fn_summary_t *summary = new (ggc_alloc <ipa_fn_summary_t> ()) 201 class ipa_fn_summary_t *summary
185 ipa_fn_summary_t(symtab, true); 202 = new (ggc_alloc_no_dtor<ipa_fn_summary_t> ()) ipa_fn_summary_t (symtab);
186 summary->disable_insertion_hook (); 203 summary->disable_insertion_hook ();
187 return summary; 204 return summary;
188 } 205 }
189 206
190 /* Remove ipa_fn_summary for all callees of NODE. */ 207 /* Remove ipa_fn_summary for all callees of NODE. */
198 215
199 virtual void duplicate (cgraph_node *src, cgraph_node *dst, 216 virtual void duplicate (cgraph_node *src, cgraph_node *dst,
200 ipa_fn_summary *src_data, ipa_fn_summary *dst_data); 217 ipa_fn_summary *src_data, ipa_fn_summary *dst_data);
201 }; 218 };
202 219
203 extern GTY(()) function_summary <ipa_fn_summary *> *ipa_fn_summaries; 220 extern GTY(()) fast_function_summary <ipa_fn_summary *, va_gc>
221 *ipa_fn_summaries;
222
223 class ipa_size_summary_t:
224 public fast_function_summary <ipa_size_summary *, va_heap>
225 {
226 public:
227 ipa_size_summary_t (symbol_table *symtab):
228 fast_function_summary <ipa_size_summary *, va_heap> (symtab)
229 {
230 disable_insertion_hook ();
231 }
232
233 virtual void duplicate (cgraph_node *, cgraph_node *,
234 ipa_size_summary *src_data,
235 ipa_size_summary *dst_data)
236 {
237 *dst_data = *src_data;
238 }
239 };
240 extern fast_function_summary <ipa_size_summary *, va_heap>
241 *ipa_size_summaries;
204 242
205 /* Information kept about callgraph edges. */ 243 /* Information kept about callgraph edges. */
206 struct ipa_call_summary 244 class ipa_call_summary
207 { 245 {
246 public:
208 /* Keep all field empty so summary dumping works during its computation. 247 /* Keep all field empty so summary dumping works during its computation.
209 This is useful for debugging. */ 248 This is useful for debugging. */
210 ipa_call_summary () 249 ipa_call_summary ()
211 : predicate (NULL), param (vNULL), call_stmt_size (0), call_stmt_time (0), 250 : predicate (NULL), param (vNULL), call_stmt_size (0), call_stmt_time (0),
212 loop_depth (0), is_return_callee_uncaptured (false) 251 loop_depth (0), is_return_callee_uncaptured (false)
234 unsigned int loop_depth; 273 unsigned int loop_depth;
235 /* Indicates whether the caller returns the value of it's callee. */ 274 /* Indicates whether the caller returns the value of it's callee. */
236 bool is_return_callee_uncaptured; 275 bool is_return_callee_uncaptured;
237 }; 276 };
238 277
239 class ipa_call_summary_t: public call_summary <ipa_call_summary *> 278 class ipa_call_summary_t: public fast_call_summary <ipa_call_summary *, va_heap>
240 { 279 {
241 public: 280 public:
242 ipa_call_summary_t (symbol_table *symtab, bool ggc): 281 ipa_call_summary_t (symbol_table *symtab):
243 call_summary <ipa_call_summary *> (symtab, ggc) {} 282 fast_call_summary <ipa_call_summary *, va_heap> (symtab) {}
244 283
245 /* Hook that is called by summary when an edge is duplicated. */ 284 /* Hook that is called by summary when an edge is duplicated. */
246 virtual void duplicate (cgraph_edge *src, cgraph_edge *dst, 285 virtual void duplicate (cgraph_edge *src, cgraph_edge *dst,
247 ipa_call_summary *src_data, 286 ipa_call_summary *src_data,
248 ipa_call_summary *dst_data); 287 ipa_call_summary *dst_data);
249 }; 288 };
250 289
251 extern call_summary <ipa_call_summary *> *ipa_call_summaries; 290 /* This object describe a context of call. That is a summary of known
291 information about its parameters. Main purpose of this context is
292 to give more realistic estimations of function runtime, size and
293 inline hints. */
294 class ipa_call_context
295 {
296 public:
297 ipa_call_context (cgraph_node *node,
298 clause_t possible_truths,
299 clause_t nonspec_possible_truths,
300 vec<tree> known_vals,
301 vec<ipa_polymorphic_call_context> known_contexts,
302 vec<ipa_agg_value_set> known_aggs,
303 vec<inline_param_summary> m_inline_param_summary);
304 ipa_call_context ()
305 : m_node(NULL)
306 {
307 }
308 void estimate_size_and_time (int *ret_size, int *ret_min_size,
309 sreal *ret_time,
310 sreal *ret_nonspecialized_time,
311 ipa_hints *ret_hints);
312 void duplicate_from (const ipa_call_context &ctx);
313 void release (bool all = false);
314 bool equal_to (const ipa_call_context &);
315 bool exists_p ()
316 {
317 return m_node != NULL;
318 }
319 private:
320 /* Called function. */
321 cgraph_node *m_node;
322 /* Clause describing what predicate conditionals can be satisfied
323 in this context if function is inlined/specialized. */
324 clause_t m_possible_truths;
325 /* Clause describing what predicate conditionals can be satisfied
326 in this context if function is kept offline. */
327 clause_t m_nonspec_possible_truths;
328 /* Inline summary maintains info about change probabilities. */
329 vec<inline_param_summary> m_inline_param_summary;
330
331 /* The following is used only to resolve indirect calls. */
332
333 /* Vector describing known values of parameters. */
334 vec<tree> m_known_vals;
335 /* Vector describing known polymorphic call contexts. */
336 vec<ipa_polymorphic_call_context> m_known_contexts;
337 /* Vector describing known aggregate values. */
338 vec<ipa_agg_value_set> m_known_aggs;
339 };
340
341 extern fast_call_summary <ipa_call_summary *, va_heap> *ipa_call_summaries;
252 342
253 /* In ipa-fnsummary.c */ 343 /* In ipa-fnsummary.c */
254 void ipa_debug_fn_summary (struct cgraph_node *); 344 void ipa_debug_fn_summary (struct cgraph_node *);
255 void ipa_dump_fn_summaries (FILE *f); 345 void ipa_dump_fn_summaries (FILE *f);
256 void ipa_dump_fn_summary (FILE *f, struct cgraph_node *node); 346 void ipa_dump_fn_summary (FILE *f, struct cgraph_node *node);
257 void ipa_dump_hints (FILE *f, ipa_hints); 347 void ipa_dump_hints (FILE *f, ipa_hints);
258 void ipa_free_fn_summary (void); 348 void ipa_free_fn_summary (void);
349 void ipa_free_size_summary (void);
259 void inline_analyze_function (struct cgraph_node *node); 350 void inline_analyze_function (struct cgraph_node *node);
260 void estimate_ipcp_clone_size_and_time (struct cgraph_node *, 351 void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
261 vec<tree>, 352 vec<tree>,
262 vec<ipa_polymorphic_call_context>, 353 vec<ipa_polymorphic_call_context>,
263 vec<ipa_agg_jump_function_p>, 354 vec<ipa_agg_value_set>,
264 int *, sreal *, sreal *, 355 int *, sreal *, sreal *,
265 ipa_hints *); 356 ipa_hints *);
266 void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge); 357 void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge);
267 void ipa_update_overall_fn_summary (struct cgraph_node *node); 358 void ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset = true);
268 void compute_fn_summary (struct cgraph_node *, bool); 359 void compute_fn_summary (struct cgraph_node *, bool);
269 360
270 361
271 void evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, 362 void evaluate_properties_for_edge (struct cgraph_edge *e,
363 bool inline_p,
272 clause_t *clause_ptr, 364 clause_t *clause_ptr,
273 clause_t *nonspec_clause_ptr, 365 clause_t *nonspec_clause_ptr,
274 vec<tree> *known_vals_ptr, 366 vec<tree> *known_vals_ptr,
275 vec<ipa_polymorphic_call_context> 367 vec<ipa_polymorphic_call_context>
276 *known_contexts_ptr, 368 *known_contexts_ptr,
277 vec<ipa_agg_jump_function_p> *); 369 vec<ipa_agg_value_set> *);
278 void estimate_node_size_and_time (struct cgraph_node *node,
279 clause_t possible_truths,
280 clause_t nonspec_possible_truths,
281 vec<tree> known_vals,
282 vec<ipa_polymorphic_call_context>,
283 vec<ipa_agg_jump_function_p> known_aggs,
284 int *ret_size, int *ret_min_size,
285 sreal *ret_time,
286 sreal *ret_nonspecialized_time,
287 ipa_hints *ret_hints,
288 vec<inline_param_summary>
289 inline_param_summary);
290 370
291 void ipa_fnsummary_c_finalize (void); 371 void ipa_fnsummary_c_finalize (void);
372 HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node);
373 void ipa_remove_from_growth_caches (struct cgraph_edge *edge);
374
375 /* Return true if EDGE is a cross module call. */
376
377 static inline bool
378 cross_module_call_p (struct cgraph_edge *edge)
379 {
380 /* Here we do not want to walk to alias target becuase ICF may create
381 cross-unit aliases. */
382 if (edge->caller->unit_id == edge->callee->unit_id)
383 return false;
384 /* If the call is to a (former) comdat function or s symbol with mutiple
385 extern inline definitions then treat is as in-module call. */
386 if (edge->callee->merged_extern_inline || edge->callee->merged_comdat
387 || DECL_COMDAT (edge->callee->decl))
388 return false;
389 return true;
390 }
292 391
293 #endif /* GCC_IPA_FNSUMMARY_H */ 392 #endif /* GCC_IPA_FNSUMMARY_H */