Line data Source code
1 : /* Timing variables for measuring compiler performance. 2 : Copyright (C) 2000-2023 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 : /* Timing variables are used to measure elapsed time in various 25 : portions of the compiler. Each measures elapsed user, system, and 26 : wall-clock time, as appropriate to and supported by the host 27 : system. 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 seconds. 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 : /* User time in this process. */ 55 : double user; 56 : 57 : /* System time (if applicable for this host platform) in this 58 : process. */ 59 : double sys; 60 : 61 : /* Wall clock time. */ 62 : double wall; 63 : 64 : /* Garbage collector memory. */ 65 : size_t ggc_mem; 66 : }; 67 : 68 : /* An enumeration of timing variable identifiers. Constructed from 69 : the contents of timevar.def. */ 70 : 71 : #define DEFTIMEVAR(identifier__, name__) \ 72 : identifier__, 73 : typedef enum 74 : { 75 : TV_NONE, 76 : #include "timevar.def" 77 : TIMEVAR_LAST 78 : } 79 : timevar_id_t; 80 : #undef DEFTIMEVAR 81 : 82 : /* A class to hold all state relating to timing. */ 83 : 84 : class timer; 85 : 86 : /* The singleton instance of timing state. 87 : 88 : This is non-NULL if timevars should be used. In GCC, this happens with 89 : the -ftime-report flag. Hence this is NULL for the common, 90 : needs-to-be-fast case, with an early reject happening for this being 91 : NULL. */ 92 : extern timer *g_timer; 93 : 94 : /* Total amount of memory allocated by garbage collector. */ 95 : extern size_t timevar_ggc_mem_total; 96 : 97 : extern void timevar_init (void); 98 : extern void timevar_start (timevar_id_t); 99 : extern void timevar_stop (timevar_id_t); 100 : extern bool timevar_cond_start (timevar_id_t); 101 : extern void timevar_cond_stop (timevar_id_t, bool); 102 : 103 : /* The public (within GCC) interface for timing. */ 104 : 105 : class timer 106 : { 107 : public: 108 : timer (); 109 : ~timer (); 110 : 111 : void start (timevar_id_t tv); 112 : void stop (timevar_id_t tv); 113 : void push (timevar_id_t tv); 114 : void pop (timevar_id_t tv); 115 : bool cond_start (timevar_id_t tv); 116 : void cond_stop (timevar_id_t tv); 117 : 118 : void push_client_item (const char *item_name); 119 : void pop_client_item (); 120 : 121 : void print (FILE *fp); 122 : 123 : const char *get_topmost_item_name () const; 124 : 125 : private: 126 : /* Private member functions. */ 127 : void validate_phases (FILE *fp) const; 128 : 129 : struct timevar_def; 130 : void push_internal (struct timevar_def *tv); 131 : void pop_internal (); 132 : static void print_row (FILE *fp, 133 : const timevar_time_def *total, 134 : const char *name, const timevar_time_def &elapsed); 135 : static bool all_zero (const timevar_time_def &elapsed); 136 : 137 : private: 138 : typedef hash_map<timevar_def *, timevar_time_def> child_map_t; 139 : 140 : /* Private type: a timing variable. */ 141 : struct timevar_def 142 : { 143 : /* Elapsed time for this variable. */ 144 : struct timevar_time_def elapsed; 145 : 146 : /* If this variable is timed independently of the timing stack, 147 : using timevar_start, this contains the start time. */ 148 : struct timevar_time_def start_time; 149 : 150 : /* The name of this timing variable. */ 151 : const char *name; 152 : 153 : /* Nonzero if this timing variable is running as a standalone 154 : timer. */ 155 : unsigned standalone : 1; 156 : 157 : /* Nonzero if this timing variable was ever started or pushed onto 158 : the timing stack. */ 159 : unsigned used : 1; 160 : 161 : child_map_t *children; 162 : }; 163 : 164 : /* Private type: an element on the timing stack 165 : Elapsed time is attributed to the topmost timing variable on the 166 : stack. */ 167 : struct timevar_stack_def 168 : { 169 : /* The timing variable at this stack level. */ 170 : struct timevar_def *timevar; 171 : 172 : /* The next lower timing variable context in the stack. */ 173 : struct timevar_stack_def *next; 174 : }; 175 : 176 : /* A class for managing a collection of named timing items, for use 177 : e.g. by libgccjit for timing client code. This class is declared 178 : inside timevar.cc to avoid everything using timevar.h 179 : from needing vec and hash_map. */ 180 : class named_items; 181 : 182 : private: 183 : 184 : /* Data members (all private). */ 185 : 186 : /* Declared timing variables. Constructed from the contents of 187 : timevar.def. */ 188 : timevar_def m_timevars[TIMEVAR_LAST]; 189 : 190 : /* The top of the timing stack. */ 191 : timevar_stack_def *m_stack; 192 : 193 : /* A list of unused (i.e. allocated and subsequently popped) 194 : timevar_stack_def instances. */ 195 : timevar_stack_def *m_unused_stack_instances; 196 : 197 : /* The time at which the topmost element on the timing stack was 198 : pushed. Time elapsed since then is attributed to the topmost 199 : element. */ 200 : timevar_time_def m_start_time; 201 : 202 : /* If non-NULL, for use when timing libgccjit's client code. */ 203 : named_items *m_jit_client_items; 204 : 205 : friend class named_items; 206 : }; 207 : 208 : /* Provided for backward compatibility. */ 209 : inline void 210 : timevar_push (timevar_id_t tv) 211 : { 212 : if (g_timer) 213 : g_timer->push (tv); 214 : } 215 : 216 : inline void 217 : timevar_pop (timevar_id_t tv) 218 : { 219 : if (g_timer) 220 : g_timer->pop (tv); 221 : } 222 : 223 : // This is a simple timevar wrapper class that pushes a timevar in its 224 : // constructor and pops the timevar in its destructor. 225 : class auto_timevar 226 : { 227 : public: 228 : auto_timevar (timer *t, timevar_id_t tv) 229 : : m_timer (t), 230 : m_tv (tv) 231 : { 232 : if (m_timer) 233 : m_timer->push (m_tv); 234 : } 235 : 236 1523765477 : explicit auto_timevar (timevar_id_t tv) 237 1523765477 : : m_timer (g_timer) 238 1523765477 : , m_tv (tv) 239 : { 240 1523765477 : if (m_timer) 241 8 : m_timer->push (m_tv); 242 1523765477 : } 243 : 244 1523727451 : ~auto_timevar () 245 : { 246 1523727451 : if (m_timer) 247 8 : m_timer->pop (m_tv); 248 1523727451 : } 249 : 250 : // Disallow copies. 251 : auto_timevar (const auto_timevar &) = delete; 252 : 253 : private: 254 : timer *m_timer; 255 : timevar_id_t m_tv; 256 : }; 257 : 258 : // As above, but use cond_start/stop. 259 : class auto_cond_timevar 260 : { 261 : public: 262 : auto_cond_timevar (timer *t, timevar_id_t tv) 263 : : m_timer (t), 264 : m_tv (tv) 265 : { 266 : start (); 267 : } 268 : 269 5539331151 : explicit auto_cond_timevar (timevar_id_t tv) 270 5539331151 : : m_timer (g_timer) 271 5539331151 : , m_tv (tv) 272 : { 273 5539331151 : start (); 274 496809550 : } 275 : 276 5539319394 : ~auto_cond_timevar () 277 : { 278 5539319394 : if (m_timer && !already_running) 279 29632 : m_timer->cond_stop (m_tv); 280 5539319394 : } 281 : 282 : // Disallow copies. 283 : auto_cond_timevar (const auto_cond_timevar &) = delete; 284 : 285 : private: 286 5539331151 : void start() 287 : { 288 5539331151 : if (m_timer) 289 40550 : already_running = m_timer->cond_start (m_tv); 290 : else 291 5539290601 : already_running = false; 292 5539331151 : } 293 : 294 : timer *m_timer; 295 : timevar_id_t m_tv; 296 : bool already_running; 297 : }; 298 : 299 : extern void print_time (const char *, long); 300 : 301 : #endif /* ! GCC_TIMEVAR_H */