1 /* IPA function body analysis.
2    Copyright (C) 2003-2018 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_SUMMARY_H
22 #define GCC_IPA_SUMMARY_H
23 
24 #include "sreal.h"
25 #include "ipa-predicate.h"
26 
27 
28 /* Hints are reasons why IPA heuristics should preffer specializing given
29    function.  They are represtented as bitmap of the following values.  */
30 enum ipa_hints_vals {
31   /* When specialization turns indirect call into a direct call,
32      it is good idea to do so.  */
33   INLINE_HINT_indirect_call = 1,
34   /* Inlining may make loop iterations or loop stride known.  It is good idea
35      to do so because it enables loop optimizatoins.  */
36   INLINE_HINT_loop_iterations = 2,
37   INLINE_HINT_loop_stride = 4,
38   /* Inlining within same strongly connected component of callgraph is often
39      a loss due to increased stack frame usage and prologue setup costs.  */
40   INLINE_HINT_same_scc = 8,
41   /* Inlining functions in strongly connected component is not such a great
42      win.  */
43   INLINE_HINT_in_scc = 16,
44   /* If function is declared inline by user, it may be good idea to inline
45      it.  Set by simple_edge_hints in ipa-inline-analysis.c.  */
46   INLINE_HINT_declared_inline = 32,
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.
49      Set by simple_edge_hints in ipa-inline-analysis.c.   */
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.  */
55   INLINE_HINT_known_hot = 256
56 };
57 
58 typedef int ipa_hints;
59 
60 /* Simple description of whether a memory load or a condition refers to a load
61    from an aggregate and if so, how and where from in the aggregate.
62    Individual fields have the same meaning like fields with the same name in
63    struct condition.  */
64 
65 struct agg_position_info
66 {
67   HOST_WIDE_INT offset;
68   bool agg_contents;
69   bool by_ref;
70 };
71 
72 /* Representation of function body size and time depending on the call
73    context.  We keep simple array of record, every containing of predicate
74    and time/size to account.  */
75 struct GTY(()) size_time_entry
76 {
77   /* Predicate for code to be executed.  */
78   predicate exec_predicate;
79   /* 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
81      the executed code paths will simplify.  */
82   predicate nonconst_predicate;
83   int size;
84   sreal GTY((skip)) time;
85 };
86 
87 /* Function inlining information.  */
88 struct GTY(()) ipa_fn_summary
89 {
90   /* Information about the function body itself.  */
91 
92   /* Estimated stack frame consumption by the function.  */
93   HOST_WIDE_INT estimated_self_stack_size;
94   /* Size of the function body.  */
95   int self_size;
96   /* Minimal size increase after inlining.  */
97   int min_size;
98 
99   /* False when there something makes inlining impossible (such as va_arg).  */
100   unsigned inlinable : 1;
101   /* True wen there is only one caller of the function before small function
102      inlining.  */
103   unsigned int single_caller : 1;
104   /* True if function contains any floating point expressions.  */
105   unsigned int fp_expressions : 1;
106 
107   /* Information about function that will result after applying all the
108      inline decisions present in the callgraph.  Generally kept up to
109      date only for functions that are not inline clones. */
110 
111   /* Estimated stack frame consumption by the function.  */
112   HOST_WIDE_INT estimated_stack_size;
113   /* Expected offset of the stack frame of function.  */
114   HOST_WIDE_INT stack_frame_offset;
115   /* Estimated size of the function after inlining.  */
116   sreal GTY((skip)) time;
117   int size;
118 
119   /* Conditional size/time information.  The summaries are being
120      merged during inlining.  */
121   conditions conds;
122   vec<size_time_entry, va_gc> *size_time_table;
123 
124   /* Predicate on when some loop in the function becomes to have known
125      bounds.   */
126   predicate * GTY((skip)) loop_iterations;
127   /* Predicate on when some loop in the function becomes to have known
128      stride.   */
129   predicate * GTY((skip)) loop_stride;
130   /* Predicate on when some array indexes become constants.  */
131   predicate * GTY((skip)) array_index;
132   /* Estimated growth for inlining all copies of the function before start
133      of small functions inlining.
134      This value will get out of date as the callers are duplicated, but
135      using up-to-date value in the badness metric mean a lot of extra
136      expenses.  */
137   int growth;
138   /* Number of SCC on the beginning of inlining process.  */
139   int scc_no;
140 
141   /* Keep all field empty so summary dumping works during its computation.
142      This is useful for debugging.  */
143   ipa_fn_summary ()
144     : estimated_self_stack_size (0), self_size (0), min_size (0),
145       inlinable (false), single_caller (false),
146       fp_expressions (false), estimated_stack_size (false),
147       stack_frame_offset (false), time (0), size (0), conds (NULL),
148       size_time_table (NULL), loop_iterations (NULL), loop_stride (NULL),
149       array_index (NULL), growth (0), scc_no (0)
150     {
151     }
152 
153   /* Record time and size under given predicates.  */
154   void account_size_time (int, sreal, const predicate &, const predicate &);
155 
156   /* Reset summary to empty state.  */
157   void reset (struct cgraph_node *node);
158 
159   /* We keep values scaled up, so fractional sizes can be accounted.  */
160   static const int size_scale = 2;
161 };
162 
163 class GTY((user)) ipa_fn_summary_t: public function_summary <ipa_fn_summary *>
164 {
165 public:
166   ipa_fn_summary_t (symbol_table *symtab, bool ggc):
167     function_summary <ipa_fn_summary *> (symtab, ggc) {}
168 
169   static ipa_fn_summary_t *create_ggc (symbol_table *symtab)
170   {
171     struct ipa_fn_summary_t *summary = new (ggc_alloc <ipa_fn_summary_t> ())
172       ipa_fn_summary_t(symtab, true);
173     summary->disable_insertion_hook ();
174     return summary;
175   }
176 
177 
178   virtual void insert (cgraph_node *, ipa_fn_summary *);
179   virtual void remove (cgraph_node *node, ipa_fn_summary *);
180   virtual void duplicate (cgraph_node *src, cgraph_node *dst,
181 			  ipa_fn_summary *src_data, ipa_fn_summary *dst_data);
182 };
183 
184 extern GTY(()) function_summary <ipa_fn_summary *> *ipa_fn_summaries;
185 
186 /* Information kept about callgraph edges.  */
187 struct ipa_call_summary
188 {
189   class predicate *predicate;
190   /* Vector indexed by parameters.  */
191   vec<inline_param_summary> param;
192   /* Estimated size and time of the call statement.  */
193   int call_stmt_size;
194   int call_stmt_time;
195   /* Depth of loop nest, 0 means no nesting.  */
196   unsigned int loop_depth;
197   /* Indicates whether the caller returns the value of it's callee.  */
198   bool is_return_callee_uncaptured;
199 
200   /* Keep all field empty so summary dumping works during its computation.
201      This is useful for debugging.  */
202   ipa_call_summary ()
203     : predicate (NULL), param (vNULL), call_stmt_size (0), call_stmt_time (0),
204       loop_depth (0)
205     {
206     }
207 
208   /* Reset inline summary to empty state.  */
209   void reset ();
210 };
211 
212 class ipa_call_summary_t: public call_summary <ipa_call_summary *>
213 {
214 public:
215   ipa_call_summary_t (symbol_table *symtab, bool ggc):
216     call_summary <ipa_call_summary *> (symtab, ggc) {}
217 
218   /* Hook that is called by summary when an edge is duplicated.  */
219   virtual void remove (cgraph_edge *cs, ipa_call_summary *);
220   /* Hook that is called by summary when an edge is duplicated.  */
221   virtual void duplicate (cgraph_edge *src, cgraph_edge *dst,
222 			  ipa_call_summary *src_data,
223 			  ipa_call_summary *dst_data);
224 };
225 
226 extern call_summary <ipa_call_summary *> *ipa_call_summaries;
227 
228 /* In ipa-fnsummary.c  */
229 void ipa_debug_fn_summary (struct cgraph_node *);
230 void ipa_dump_fn_summaries (FILE *f);
231 void ipa_dump_fn_summary (FILE *f, struct cgraph_node *node);
232 void ipa_dump_hints (FILE *f, ipa_hints);
233 void ipa_free_fn_summary (void);
234 void inline_analyze_function (struct cgraph_node *node);
235 void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
236 					vec<tree>,
237 					vec<ipa_polymorphic_call_context>,
238 					vec<ipa_agg_jump_function_p>,
239 					int *, sreal *, sreal *,
240 				        ipa_hints *);
241 void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge);
242 void ipa_update_overall_fn_summary (struct cgraph_node *node);
243 void compute_fn_summary (struct cgraph_node *, bool);
244 
245 
246 void evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
247 				   clause_t *clause_ptr,
248 				   clause_t *nonspec_clause_ptr,
249 				   vec<tree> *known_vals_ptr,
250 				   vec<ipa_polymorphic_call_context>
251 				   *known_contexts_ptr,
252 				   vec<ipa_agg_jump_function_p> *);
253 void estimate_node_size_and_time (struct cgraph_node *node,
254 				  clause_t possible_truths,
255 				  clause_t nonspec_possible_truths,
256 				  vec<tree> known_vals,
257 				  vec<ipa_polymorphic_call_context>,
258 				  vec<ipa_agg_jump_function_p> known_aggs,
259 				  int *ret_size, int *ret_min_size,
260 				  sreal *ret_time,
261 				  sreal *ret_nonspecialized_time,
262 				  ipa_hints *ret_hints,
263 				  vec<inline_param_summary>
264 				  inline_param_summary);
265 
266 void ipa_fnsummary_c_finalize (void);
267 
268 #endif /* GCC_IPA_FNSUMMARY_H */
269