Line data Source code
1 : /* Timing variables for measuring compiler performance.
2 : Copyright (C) 2000-2026 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 17603306065 : timevar_push (timevar_id_t tv)
207 : {
208 17603306065 : if (g_timer)
209 618453 : g_timer->push (tv);
210 17603306065 : }
211 :
212 : inline void
213 17603303830 : timevar_pop (timevar_id_t tv)
214 : {
215 17603303830 : if (g_timer)
216 618453 : g_timer->pop (tv);
217 17603303830 : }
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 37731672 : auto_timevar (timer *t, timevar_id_t tv)
225 37731672 : : m_timer (t),
226 37731672 : m_tv (tv)
227 : {
228 37731672 : if (m_timer)
229 1606 : m_timer->push (m_tv);
230 : }
231 :
232 3671257754 : explicit auto_timevar (timevar_id_t tv)
233 3671257754 : : m_timer (g_timer)
234 3671257754 : , m_tv (tv)
235 : {
236 3671257754 : if (m_timer)
237 550 : m_timer->push (m_tv);
238 3671257754 : }
239 :
240 3708962219 : ~auto_timevar ()
241 : {
242 3708962219 : if (m_timer)
243 2156 : m_timer->pop (m_tv);
244 3708962219 : }
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 11562949467 : explicit auto_cond_timevar (timevar_id_t tv)
266 11562949467 : : m_timer (g_timer)
267 11562949467 : , m_tv (tv)
268 : {
269 11562949467 : start ();
270 944903364 : }
271 :
272 11562935910 : ~auto_cond_timevar ()
273 : {
274 11562935910 : if (m_timer && !already_running)
275 67755 : m_timer->cond_stop (m_tv);
276 11562935910 : }
277 :
278 : // Disallow copies.
279 : auto_cond_timevar (const auto_cond_timevar &) = delete;
280 :
281 : private:
282 11562949467 : void start()
283 : {
284 11562949467 : if (m_timer)
285 91585 : already_running = m_timer->cond_start (m_tv);
286 : else
287 11562857882 : already_running = false;
288 11562949467 : }
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 */
|