Mercurial > hg > CbC > CbC_gcc
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 */ |