Branch data Line data Source code
1 : : /* Timing variables for measuring compiler performance.
2 : : Copyright (C) 2000-2025 Free Software Foundation, Inc.
3 : : Contributed by Alex Samuel <samuel@codesourcery.com>
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it
8 : : under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3, or (at your option)
10 : : any later version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT
13 : : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 : : or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 : : License 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_TIMEVAR_H
22 : : #define GCC_TIMEVAR_H
23 : :
24 : : namespace json { class value; }
25 : :
26 : : /* Timing variables are used to measure elapsed time in various
27 : : portions of the compiler. Each measures wall time.
28 : :
29 : : Timing variables are defined using the DEFTIMEVAR macro in
30 : : timevar.def. Each has an enumeral identifier, used when referring
31 : : to the timing variable in code, and a character string name.
32 : :
33 : : Timing variables can be used in two ways:
34 : :
35 : : - On the timing stack, using timevar_push and timevar_pop.
36 : : Timing variables may be pushed onto the stack; elapsed time is
37 : : attributed to the topmost timing variable on the stack. When
38 : : another variable is pushed on, the previous topmost variable is
39 : : `paused' until the pushed variable is popped back off.
40 : :
41 : : - As a standalone timer, using timevar_start and timevar_stop.
42 : : All time elapsed between the two calls is attributed to the
43 : : variable.
44 : : */
45 : :
46 : : /* This structure stores the various varieties of time that can be
47 : : measured. Times are stored in nanoseconds. The time may be an
48 : : absolute time or a time difference; in the former case, the time
49 : : base is undefined, except that the difference between two times
50 : : produces a valid time difference. */
51 : :
52 : : struct timevar_time_def
53 : : {
54 : : /* Wall clock time. */
55 : : uint64_t wall;
56 : :
57 : : /* Garbage collector memory. */
58 : : size_t ggc_mem;
59 : : };
60 : :
61 : : /* An enumeration of timing variable identifiers. Constructed from
62 : : the contents of timevar.def. */
63 : :
64 : : #define DEFTIMEVAR(identifier__, name__) \
65 : : identifier__,
66 : : typedef enum
67 : : {
68 : : TV_NONE,
69 : : #include "timevar.def"
70 : : TIMEVAR_LAST
71 : : }
72 : : timevar_id_t;
73 : : #undef DEFTIMEVAR
74 : :
75 : : /* A class to hold all state relating to timing. */
76 : :
77 : : class timer;
78 : :
79 : : /* The singleton instance of timing state.
80 : :
81 : : This is non-NULL if timevars should be used. In GCC, this happens with
82 : : the -ftime-report flag. Hence this is NULL for the common,
83 : : needs-to-be-fast case, with an early reject happening for this being
84 : : NULL. */
85 : : extern timer *g_timer;
86 : :
87 : : /* Total amount of memory allocated by garbage collector. */
88 : : extern size_t timevar_ggc_mem_total;
89 : :
90 : : extern void timevar_init (void);
91 : : extern void timevar_start (timevar_id_t);
92 : : extern void timevar_stop (timevar_id_t);
93 : : extern bool timevar_cond_start (timevar_id_t);
94 : : extern void timevar_cond_stop (timevar_id_t, bool);
95 : :
96 : : /* The public (within GCC) interface for timing. */
97 : :
98 : : class timer
99 : : {
100 : : public:
101 : : timer ();
102 : : ~timer ();
103 : :
104 : : void start (timevar_id_t tv);
105 : : void stop (timevar_id_t tv);
106 : : void push (timevar_id_t tv);
107 : : void pop (timevar_id_t tv);
108 : : bool cond_start (timevar_id_t tv);
109 : : void cond_stop (timevar_id_t tv);
110 : :
111 : : void push_client_item (const char *item_name);
112 : : void pop_client_item ();
113 : :
114 : : void print (FILE *fp);
115 : : std::unique_ptr<json::value> make_json () const;
116 : :
117 : : const char *get_topmost_item_name () const;
118 : :
119 : : private:
120 : : /* Private member functions. */
121 : : void validate_phases (FILE *fp) const;
122 : :
123 : : struct timevar_def;
124 : : void push_internal (struct timevar_def *tv);
125 : : void pop_internal ();
126 : : static void print_row (FILE *fp,
127 : : const timevar_time_def *total,
128 : : const char *name, const timevar_time_def &elapsed);
129 : : static bool all_zero (const timevar_time_def &elapsed);
130 : :
131 : : private:
132 : : typedef hash_map<timevar_def *, timevar_time_def> child_map_t;
133 : :
134 : : /* Private type: a timing variable. */
135 : : struct timevar_def
136 : : {
137 : : std::unique_ptr<json::value> make_json () const;
138 : :
139 : : /* Elapsed time for this variable. */
140 : : struct timevar_time_def elapsed;
141 : :
142 : : /* If this variable is timed independently of the timing stack,
143 : : using timevar_start, this contains the start time. */
144 : : struct timevar_time_def start_time;
145 : :
146 : : /* The name of this timing variable. */
147 : : const char *name;
148 : :
149 : : /* Nonzero if this timing variable is running as a standalone
150 : : timer. */
151 : : unsigned standalone : 1;
152 : :
153 : : /* Nonzero if this timing variable was ever started or pushed onto
154 : : the timing stack. */
155 : : unsigned used : 1;
156 : :
157 : : child_map_t *children;
158 : : };
159 : :
160 : : /* Private type: an element on the timing stack
161 : : Elapsed time is attributed to the topmost timing variable on the
162 : : stack. */
163 : : struct timevar_stack_def
164 : : {
165 : : /* The timing variable at this stack level. */
166 : : struct timevar_def *timevar;
167 : :
168 : : /* The next lower timing variable context in the stack. */
169 : : struct timevar_stack_def *next;
170 : : };
171 : :
172 : : /* A class for managing a collection of named timing items, for use
173 : : e.g. by libgccjit for timing client code. This class is declared
174 : : inside timevar.cc to avoid everything using timevar.h
175 : : from needing vec and hash_map. */
176 : : class named_items;
177 : :
178 : : private:
179 : :
180 : : /* Data members (all private). */
181 : :
182 : : /* Declared timing variables. Constructed from the contents of
183 : : timevar.def. */
184 : : timevar_def m_timevars[TIMEVAR_LAST];
185 : :
186 : : /* The top of the timing stack. */
187 : : timevar_stack_def *m_stack;
188 : :
189 : : /* A list of unused (i.e. allocated and subsequently popped)
190 : : timevar_stack_def instances. */
191 : : timevar_stack_def *m_unused_stack_instances;
192 : :
193 : : /* The time at which the topmost element on the timing stack was
194 : : pushed. Time elapsed since then is attributed to the topmost
195 : : element. */
196 : : timevar_time_def m_start_time;
197 : :
198 : : /* If non-NULL, for use when timing libgccjit's client code. */
199 : : named_items *m_jit_client_items;
200 : :
201 : : friend class named_items;
202 : : };
203 : :
204 : : /* Provided for backward compatibility. */
205 : : inline void
206 : 15746301656 : timevar_push (timevar_id_t tv)
207 : : {
208 : 15746301656 : if (g_timer)
209 : 612997 : g_timer->push (tv);
210 : 15746301656 : }
211 : :
212 : : inline void
213 : 15746299652 : timevar_pop (timevar_id_t tv)
214 : : {
215 : 15746299652 : if (g_timer)
216 : 612997 : g_timer->pop (tv);
217 : 15746299652 : }
218 : :
219 : : // This is a simple timevar wrapper class that pushes a timevar in its
220 : : // constructor and pops the timevar in its destructor.
221 : : class auto_timevar
222 : : {
223 : : public:
224 : 38277101 : auto_timevar (timer *t, timevar_id_t tv)
225 : 38277101 : : m_timer (t),
226 : 38277101 : m_tv (tv)
227 : : {
228 : 38277101 : if (m_timer)
229 : 1606 : m_timer->push (m_tv);
230 : : }
231 : :
232 : 2268514958 : explicit auto_timevar (timevar_id_t tv)
233 : 2268514958 : : m_timer (g_timer)
234 : 2268514958 : , m_tv (tv)
235 : : {
236 : 2268514958 : if (m_timer)
237 : 538 : m_timer->push (m_tv);
238 : 2268514958 : }
239 : :
240 : 2306764853 : ~auto_timevar ()
241 : : {
242 : 2306764853 : if (m_timer)
243 : 2144 : m_timer->pop (m_tv);
244 : 2306764853 : }
245 : :
246 : : // Disallow copies.
247 : : auto_timevar (const auto_timevar &) = delete;
248 : :
249 : : private:
250 : : timer *m_timer;
251 : : timevar_id_t m_tv;
252 : : };
253 : :
254 : : // As above, but use cond_start/stop.
255 : : class auto_cond_timevar
256 : : {
257 : : public:
258 : : auto_cond_timevar (timer *t, timevar_id_t tv)
259 : : : m_timer (t),
260 : : m_tv (tv)
261 : : {
262 : : start ();
263 : : }
264 : :
265 : 8497772122 : explicit auto_cond_timevar (timevar_id_t tv)
266 : 8497772122 : : m_timer (g_timer)
267 : 8497772122 : , m_tv (tv)
268 : : {
269 : 8497772122 : start ();
270 : 723684534 : }
271 : :
272 : 8497758565 : ~auto_cond_timevar ()
273 : : {
274 : 8497758565 : if (m_timer && !already_running)
275 : 65469 : m_timer->cond_stop (m_tv);
276 : 8497758565 : }
277 : :
278 : : // Disallow copies.
279 : : auto_cond_timevar (const auto_cond_timevar &) = delete;
280 : :
281 : : private:
282 : 8497772122 : void start()
283 : : {
284 : 8497772122 : if (m_timer)
285 : 88459 : already_running = m_timer->cond_start (m_tv);
286 : : else
287 : 8497683663 : already_running = false;
288 : 8497772122 : }
289 : :
290 : : timer *m_timer;
291 : : timevar_id_t m_tv;
292 : : bool already_running;
293 : : };
294 : :
295 : : extern void print_time (const char *, long);
296 : :
297 : : #endif /* ! GCC_TIMEVAR_H */
|