1 1.1 mrg /* Timing variables for measuring compiler performance. 2 1.1 mrg Copyright (C) 2000-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Alex Samuel <samuel (at) codesourcery.com> 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify it under 8 1.1 mrg the terms of the GNU General Public License as published by the Free 9 1.1 mrg Software Foundation; either version 3, or (at your option) any later 10 1.1 mrg version. 11 1.1 mrg 12 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 1.1 mrg for more details. 16 1.1 mrg 17 1.1 mrg You should have received a copy of the GNU General Public License 18 1.1 mrg along with GCC; see the file COPYING3. If not see 19 1.1 mrg <http://www.gnu.org/licenses/>. */ 20 1.1 mrg 21 1.1 mrg #include "config.h" 22 1.1 mrg #include "system.h" 23 1.1 mrg #include "coretypes.h" 24 1.1 mrg #include "timevar.h" 25 1.1 mrg #include "options.h" 26 1.1 mrg 27 1.1 mrg #ifndef HAVE_CLOCK_T 28 1.1 mrg typedef int clock_t; 29 1.1 mrg #endif 30 1.1 mrg 31 1.1 mrg #ifndef HAVE_STRUCT_TMS 32 1.1 mrg struct tms 33 1.1 mrg { 34 1.1 mrg clock_t tms_utime; 35 1.1 mrg clock_t tms_stime; 36 1.1 mrg clock_t tms_cutime; 37 1.1 mrg clock_t tms_cstime; 38 1.1 mrg }; 39 1.1 mrg #endif 40 1.1 mrg 41 1.1 mrg #ifndef RUSAGE_SELF 42 1.1 mrg # define RUSAGE_SELF 0 43 1.1 mrg #endif 44 1.1 mrg 45 1.1 mrg /* Calculation of scale factor to convert ticks to microseconds. 46 1.1 mrg We mustn't use CLOCKS_PER_SEC except with clock(). */ 47 1.1 mrg #if HAVE_SYSCONF && defined _SC_CLK_TCK 48 1.1 mrg # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */ 49 1.1 mrg #else 50 1.1 mrg # ifdef CLK_TCK 51 1.1 mrg # define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */ 52 1.1 mrg # else 53 1.1 mrg # ifdef HZ 54 1.1 mrg # define TICKS_PER_SECOND HZ /* traditional UNIX */ 55 1.1 mrg # else 56 1.1 mrg # define TICKS_PER_SECOND 100 /* often the correct value */ 57 1.1 mrg # endif 58 1.1 mrg # endif 59 1.1 mrg #endif 60 1.1 mrg 61 1.1 mrg /* Prefer times to getrusage to clock (each gives successively less 62 1.1 mrg information). */ 63 1.1 mrg #ifdef HAVE_TIMES 64 1.1 mrg # if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES 65 1.1 mrg extern clock_t times (struct tms *); 66 1.1 mrg # endif 67 1.1 mrg # define USE_TIMES 68 1.1 mrg # define HAVE_USER_TIME 69 1.1 mrg # define HAVE_SYS_TIME 70 1.1 mrg # define HAVE_WALL_TIME 71 1.1 mrg #else 72 1.1 mrg #ifdef HAVE_GETRUSAGE 73 1.1 mrg # if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE 74 1.1 mrg extern int getrusage (int, struct rusage *); 75 1.1 mrg # endif 76 1.1 mrg # define USE_GETRUSAGE 77 1.1 mrg # define HAVE_USER_TIME 78 1.1 mrg # define HAVE_SYS_TIME 79 1.1 mrg #else 80 1.1 mrg #ifdef HAVE_CLOCK 81 1.1 mrg # if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK 82 1.1 mrg extern clock_t clock (void); 83 1.1 mrg # endif 84 1.1 mrg # define USE_CLOCK 85 1.1 mrg # define HAVE_USER_TIME 86 1.1 mrg #endif 87 1.1 mrg #endif 88 1.1 mrg #endif 89 1.1 mrg 90 1.1 mrg /* libc is very likely to have snuck a call to sysconf() into one of 91 1.1 mrg the underlying constants, and that can be very slow, so we have to 92 1.1 mrg precompute them. Whose wonderful idea was it to make all those 93 1.1 mrg _constants_ variable at run time, anyway? */ 94 1.1 mrg #ifdef USE_TIMES 95 1.1 mrg static double ticks_to_msec; 96 1.1 mrg #define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND) 97 1.1 mrg #endif 98 1.1 mrg 99 1.1 mrg #ifdef USE_CLOCK 100 1.1 mrg static double clocks_to_msec; 101 1.1 mrg #define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC) 102 1.1 mrg #endif 103 1.1 mrg 104 1.1 mrg /* Non-NULL if timevars should be used. In GCC, this happens with 105 1.1 mrg the -ftime-report flag. */ 106 1.1 mrg 107 1.1 mrg timer *g_timer; 108 1.1 mrg 109 1.1 mrg /* Total amount of memory allocated by garbage collector. */ 110 1.1 mrg 111 1.1 mrg size_t timevar_ggc_mem_total; 112 1.1 mrg 113 1.1 mrg /* The amount of memory that will cause us to report the timevar even 114 1.1 mrg if the time spent is not significant. */ 115 1.1 mrg 116 1.1 mrg #define GGC_MEM_BOUND (1 << 20) 117 1.1 mrg 118 1.1 mrg /* See timevar.h for an explanation of timing variables. */ 119 1.1 mrg 120 1.1 mrg static void get_time (struct timevar_time_def *); 121 1.1 mrg static void timevar_accumulate (struct timevar_time_def *, 122 1.1 mrg struct timevar_time_def *, 123 1.1 mrg struct timevar_time_def *); 124 1.1 mrg 125 1.1 mrg /* The implementation of timing events for jit client code, allowing 126 1.1 mrg arbitrary named items to appear on the timing stack. */ 127 1.1 mrg 128 1.1 mrg class timer::named_items 129 1.1 mrg { 130 1.1 mrg public: 131 1.1 mrg named_items (timer *t); 132 1.1 mrg ~named_items (); 133 1.1 mrg 134 1.1 mrg void push (const char *item_name); 135 1.1 mrg void pop (); 136 1.1 mrg void print (FILE *fp, const timevar_time_def *total); 137 1.1 mrg 138 1.1 mrg private: 139 1.1 mrg /* Which timer instance does this relate to? */ 140 1.1 mrg timer *m_timer; 141 1.1 mrg 142 1.1 mrg /* Dictionary, mapping from item names to timevar_def. 143 1.1 mrg Note that currently we merely store/compare the raw string 144 1.1 mrg pointers provided by client code; we don't take a copy, 145 1.1 mrg or use strcmp. */ 146 1.1 mrg hash_map <const char *, timer::timevar_def> m_hash_map; 147 1.1 mrg 148 1.1 mrg /* The order in which items were originally inserted. */ 149 1.1 mrg auto_vec <const char *> m_names; 150 1.1 mrg }; 151 1.1 mrg 152 1.1 mrg /* The constructor for class timer::named_items. */ 153 1.1 mrg 154 1.1 mrg timer::named_items::named_items (timer *t) 155 1.1 mrg : m_timer (t), 156 1.1 mrg m_hash_map (), 157 1.1 mrg m_names () 158 1.1 mrg { 159 1.1 mrg } 160 1.1 mrg 161 1.1 mrg /* The destructor for class timer::named_items. */ 162 1.1 mrg 163 1.1 mrg timer::named_items::~named_items () 164 1.1 mrg { 165 1.1 mrg } 166 1.1 mrg 167 1.1 mrg /* Push the named item onto the timer stack. */ 168 1.1 mrg 169 1.1 mrg void 170 1.1 mrg timer::named_items::push (const char *item_name) 171 1.1 mrg { 172 1.1 mrg gcc_assert (item_name); 173 1.1 mrg 174 1.1 mrg bool existed; 175 1.1 mrg timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed); 176 1.1 mrg if (!existed) 177 1.1 mrg { 178 1.1 mrg def->elapsed.user = 0; 179 1.1 mrg def->elapsed.sys = 0; 180 1.1 mrg def->elapsed.wall = 0; 181 1.1 mrg def->name = item_name; 182 1.1 mrg def->standalone = 0; 183 1.1 mrg m_names.safe_push (item_name); 184 1.1 mrg } 185 1.1 mrg m_timer->push_internal (def); 186 1.1 mrg } 187 1.1 mrg 188 1.1 mrg /* Pop the top item from the timer stack. */ 189 1.1 mrg 190 1.1 mrg void 191 1.1 mrg timer::named_items::pop () 192 1.1 mrg { 193 1.1 mrg m_timer->pop_internal (); 194 1.1 mrg } 195 1.1 mrg 196 1.1 mrg /* Print the given client item. Helper function for timer::print. */ 197 1.1 mrg 198 1.1 mrg void 199 1.1 mrg timer::named_items::print (FILE *fp, const timevar_time_def *total) 200 1.1 mrg { 201 1.1 mrg fprintf (fp, "Client items:\n"); 202 1.1 mrg for (const char *item_name : m_names) 203 1.1 mrg { 204 1.1 mrg timer::timevar_def *def = m_hash_map.get (item_name); 205 1.1 mrg gcc_assert (def); 206 1.1 mrg m_timer->print_row (fp, total, def->name, def->elapsed); 207 1.1 mrg } 208 1.1 mrg } 209 1.1 mrg 210 1.1 mrg /* Fill the current times into TIME. The definition of this function 211 1.1 mrg also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and 212 1.1 mrg HAVE_WALL_TIME macros. */ 213 1.1 mrg 214 1.1 mrg static void 215 1.1 mrg get_time (struct timevar_time_def *now) 216 1.1 mrg { 217 1.1 mrg now->user = 0; 218 1.1 mrg now->sys = 0; 219 1.1 mrg now->wall = 0; 220 1.1 mrg now->ggc_mem = timevar_ggc_mem_total; 221 1.1 mrg 222 1.1 mrg { 223 1.1 mrg #ifdef USE_TIMES 224 1.1 mrg struct tms tms; 225 1.1 mrg now->wall = times (&tms) * ticks_to_msec; 226 1.1 mrg now->user = tms.tms_utime * ticks_to_msec; 227 1.1 mrg now->sys = tms.tms_stime * ticks_to_msec; 228 1.1 mrg #endif 229 1.1 mrg #ifdef USE_GETRUSAGE 230 1.1 mrg struct rusage rusage; 231 1.1 mrg getrusage (RUSAGE_SELF, &rusage); 232 1.1 mrg now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6; 233 1.1 mrg now->sys = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6; 234 1.1 mrg #endif 235 1.1 mrg #ifdef USE_CLOCK 236 1.1 mrg now->user = clock () * clocks_to_msec; 237 1.1 mrg #endif 238 1.1 mrg } 239 1.1 mrg } 240 1.1 mrg 241 1.1 mrg /* Add the difference between STOP_TIME and START_TIME to TIMER. */ 242 1.1 mrg 243 1.1 mrg static void 244 1.1 mrg timevar_accumulate (struct timevar_time_def *timer, 245 1.1 mrg struct timevar_time_def *start_time, 246 1.1 mrg struct timevar_time_def *stop_time) 247 1.1 mrg { 248 1.1 mrg timer->user += stop_time->user - start_time->user; 249 1.1 mrg timer->sys += stop_time->sys - start_time->sys; 250 1.1 mrg timer->wall += stop_time->wall - start_time->wall; 251 1.1 mrg timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem; 252 1.1 mrg } 253 1.1 mrg 254 1.1 mrg /* Class timer's constructor. */ 255 1.1 mrg 256 1.1 mrg timer::timer () : 257 1.1 mrg m_stack (NULL), 258 1.1 mrg m_unused_stack_instances (NULL), 259 1.1 mrg m_start_time (), 260 1.1 mrg m_jit_client_items (NULL) 261 1.1 mrg { 262 1.1 mrg /* Zero all elapsed times. */ 263 1.1 mrg memset (m_timevars, 0, sizeof (m_timevars)); 264 1.1 mrg 265 1.1 mrg /* Initialize the names of timing variables. */ 266 1.1 mrg #define DEFTIMEVAR(identifier__, name__) \ 267 1.1 mrg m_timevars[identifier__].name = name__; 268 1.1 mrg #include "timevar.def" 269 1.1 mrg #undef DEFTIMEVAR 270 1.1 mrg 271 1.1 mrg /* Initialize configuration-specific state. 272 1.1 mrg Ideally this would be one-time initialization. */ 273 1.1 mrg #ifdef USE_TIMES 274 1.1 mrg ticks_to_msec = TICKS_TO_MSEC; 275 1.1 mrg #endif 276 1.1 mrg #ifdef USE_CLOCK 277 1.1 mrg clocks_to_msec = CLOCKS_TO_MSEC; 278 1.1 mrg #endif 279 1.1 mrg } 280 1.1 mrg 281 1.1 mrg /* Class timer's destructor. */ 282 1.1 mrg 283 1.1 mrg timer::~timer () 284 1.1 mrg { 285 1.1 mrg timevar_stack_def *iter, *next; 286 1.1 mrg 287 1.1 mrg for (iter = m_stack; iter; iter = next) 288 1.1 mrg { 289 1.1 mrg next = iter->next; 290 1.1 mrg free (iter); 291 1.1 mrg } 292 1.1 mrg for (iter = m_unused_stack_instances; iter; iter = next) 293 1.1 mrg { 294 1.1 mrg next = iter->next; 295 1.1 mrg free (iter); 296 1.1 mrg } 297 1.1 mrg for (unsigned i = 0; i < TIMEVAR_LAST; ++i) 298 1.1 mrg delete m_timevars[i].children; 299 1.1 mrg 300 1.1 mrg delete m_jit_client_items; 301 1.1 mrg } 302 1.1 mrg 303 1.1 mrg /* Initialize timing variables. */ 304 1.1 mrg 305 1.1 mrg void 306 1.1 mrg timevar_init (void) 307 1.1 mrg { 308 1.1 mrg if (g_timer) 309 1.1 mrg return; 310 1.1 mrg 311 1.1 mrg g_timer = new timer (); 312 1.1 mrg } 313 1.1 mrg 314 1.1 mrg /* Push TIMEVAR onto the timing stack. No further elapsed time is 315 1.1 mrg attributed to the previous topmost timing variable on the stack; 316 1.1 mrg subsequent elapsed time is attributed to TIMEVAR, until it is 317 1.1 mrg popped or another element is pushed on top. 318 1.1 mrg 319 1.1 mrg TIMEVAR cannot be running as a standalone timer. */ 320 1.1 mrg 321 1.1 mrg void 322 1.1 mrg timer::push (timevar_id_t timevar) 323 1.1 mrg { 324 1.1 mrg struct timevar_def *tv = &m_timevars[timevar]; 325 1.1 mrg push_internal (tv); 326 1.1 mrg } 327 1.1 mrg 328 1.1 mrg /* Push TV onto the timing stack, either one of the builtin ones 329 1.1 mrg for a timevar_id_t, or one provided by client code to libgccjit. */ 330 1.1 mrg 331 1.1 mrg void 332 1.1 mrg timer::push_internal (struct timevar_def *tv) 333 1.1 mrg { 334 1.1 mrg struct timevar_stack_def *context; 335 1.1 mrg struct timevar_time_def now; 336 1.1 mrg 337 1.1 mrg gcc_assert (tv); 338 1.1 mrg 339 1.1 mrg /* Mark this timing variable as used. */ 340 1.1 mrg tv->used = 1; 341 1.1 mrg 342 1.1 mrg /* Can't push a standalone timer. */ 343 1.1 mrg gcc_assert (!tv->standalone); 344 1.1 mrg 345 1.1 mrg /* What time is it? */ 346 1.1 mrg get_time (&now); 347 1.1 mrg 348 1.1 mrg /* If the stack isn't empty, attribute the current elapsed time to 349 1.1 mrg the old topmost element. */ 350 1.1 mrg if (m_stack) 351 1.1 mrg timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now); 352 1.1 mrg 353 1.1 mrg /* Reset the start time; from now on, time is attributed to 354 1.1 mrg TIMEVAR. */ 355 1.1 mrg m_start_time = now; 356 1.1 mrg 357 1.1 mrg /* See if we have a previously-allocated stack instance. If so, 358 1.1 mrg take it off the list. If not, malloc a new one. */ 359 1.1 mrg if (m_unused_stack_instances != NULL) 360 1.1 mrg { 361 1.1 mrg context = m_unused_stack_instances; 362 1.1 mrg m_unused_stack_instances = m_unused_stack_instances->next; 363 1.1 mrg } 364 1.1 mrg else 365 1.1 mrg context = XNEW (struct timevar_stack_def); 366 1.1 mrg 367 1.1 mrg /* Fill it in and put it on the stack. */ 368 1.1 mrg context->timevar = tv; 369 1.1 mrg context->next = m_stack; 370 1.1 mrg m_stack = context; 371 1.1 mrg } 372 1.1 mrg 373 1.1 mrg /* Pop the topmost timing variable element off the timing stack. The 374 1.1 mrg popped variable must be TIMEVAR. Elapsed time since the that 375 1.1 mrg element was pushed on, or since it was last exposed on top of the 376 1.1 mrg stack when the element above it was popped off, is credited to that 377 1.1 mrg timing variable. */ 378 1.1 mrg 379 1.1 mrg void 380 1.1 mrg timer::pop (timevar_id_t timevar) 381 1.1 mrg { 382 1.1 mrg gcc_assert (&m_timevars[timevar] == m_stack->timevar); 383 1.1 mrg 384 1.1 mrg pop_internal (); 385 1.1 mrg } 386 1.1 mrg 387 1.1 mrg /* Pop the topmost item from the stack, either one of the builtin ones 388 1.1 mrg for a timevar_id_t, or one provided by client code to libgccjit. */ 389 1.1 mrg 390 1.1 mrg void 391 1.1 mrg timer::pop_internal () 392 1.1 mrg { 393 1.1 mrg struct timevar_time_def now; 394 1.1 mrg struct timevar_stack_def *popped = m_stack; 395 1.1 mrg 396 1.1 mrg /* What time is it? */ 397 1.1 mrg get_time (&now); 398 1.1 mrg 399 1.1 mrg /* Attribute the elapsed time to the element we're popping. */ 400 1.1 mrg timevar_accumulate (&popped->timevar->elapsed, &m_start_time, &now); 401 1.1 mrg 402 1.1 mrg /* Take the item off the stack. */ 403 1.1 mrg m_stack = m_stack->next; 404 1.1 mrg 405 1.1 mrg /* Record the elapsed sub-time to the parent as well. */ 406 1.1 mrg if (m_stack && time_report_details) 407 1.1 mrg { 408 1.1 mrg if (! m_stack->timevar->children) 409 1.1 mrg m_stack->timevar->children = new child_map_t (5); 410 1.1 mrg bool existed_p; 411 1.1 mrg timevar_time_def &time 412 1.1 mrg = m_stack->timevar->children->get_or_insert (popped->timevar, &existed_p); 413 1.1 mrg if (! existed_p) 414 1.1 mrg memset (&time, 0, sizeof (timevar_time_def)); 415 1.1 mrg timevar_accumulate (&time, &m_start_time, &now); 416 1.1 mrg } 417 1.1 mrg 418 1.1 mrg /* Reset the start time; from now on, time is attributed to the 419 1.1 mrg element just exposed on the stack. */ 420 1.1 mrg m_start_time = now; 421 1.1 mrg 422 1.1 mrg /* Don't delete the stack element; instead, add it to the list of 423 1.1 mrg unused elements for later use. */ 424 1.1 mrg popped->next = m_unused_stack_instances; 425 1.1 mrg m_unused_stack_instances = popped; 426 1.1 mrg } 427 1.1 mrg 428 1.1 mrg /* Start timing TIMEVAR independently of the timing stack. Elapsed 429 1.1 mrg time until timevar_stop is called for the same timing variable is 430 1.1 mrg attributed to TIMEVAR. */ 431 1.1 mrg 432 1.1 mrg void 433 1.1 mrg timevar_start (timevar_id_t timevar) 434 1.1 mrg { 435 1.1 mrg if (!g_timer) 436 1.1 mrg return; 437 1.1 mrg 438 1.1 mrg g_timer->start (timevar); 439 1.1 mrg } 440 1.1 mrg 441 1.1 mrg /* See timevar_start above. */ 442 1.1 mrg 443 1.1 mrg void 444 1.1 mrg timer::start (timevar_id_t timevar) 445 1.1 mrg { 446 1.1 mrg struct timevar_def *tv = &m_timevars[timevar]; 447 1.1 mrg 448 1.1 mrg /* Mark this timing variable as used. */ 449 1.1 mrg tv->used = 1; 450 1.1 mrg 451 1.1 mrg /* Don't allow the same timing variable to be started more than 452 1.1 mrg once. */ 453 1.1 mrg gcc_assert (!tv->standalone); 454 1.1 mrg tv->standalone = 1; 455 1.1 mrg 456 1.1 mrg get_time (&tv->start_time); 457 1.1 mrg } 458 1.1 mrg 459 1.1 mrg /* Stop timing TIMEVAR. Time elapsed since timevar_start was called 460 1.1 mrg is attributed to it. */ 461 1.1 mrg 462 1.1 mrg void 463 1.1 mrg timevar_stop (timevar_id_t timevar) 464 1.1 mrg { 465 1.1 mrg if (!g_timer) 466 1.1 mrg return; 467 1.1 mrg 468 1.1 mrg g_timer->stop (timevar); 469 1.1 mrg } 470 1.1 mrg 471 1.1 mrg /* See timevar_stop above. */ 472 1.1 mrg 473 1.1 mrg void 474 1.1 mrg timer::stop (timevar_id_t timevar) 475 1.1 mrg { 476 1.1 mrg struct timevar_def *tv = &m_timevars[timevar]; 477 1.1 mrg struct timevar_time_def now; 478 1.1 mrg 479 1.1 mrg /* TIMEVAR must have been started via timevar_start. */ 480 1.1 mrg gcc_assert (tv->standalone); 481 1.1 mrg tv->standalone = 0; /* Enable a restart. */ 482 1.1 mrg 483 1.1 mrg get_time (&now); 484 1.1 mrg timevar_accumulate (&tv->elapsed, &tv->start_time, &now); 485 1.1 mrg } 486 1.1 mrg 487 1.1 mrg 488 1.1 mrg /* Conditionally start timing TIMEVAR independently of the timing stack. 489 1.1 mrg If the timer is already running, leave it running and return true. 490 1.1 mrg Otherwise, start the timer and return false. 491 1.1 mrg Elapsed time until the corresponding timevar_cond_stop 492 1.1 mrg is called for the same timing variable is attributed to TIMEVAR. */ 493 1.1 mrg 494 1.1 mrg bool 495 1.1 mrg timevar_cond_start (timevar_id_t timevar) 496 1.1 mrg { 497 1.1 mrg if (!g_timer) 498 1.1 mrg return false; 499 1.1 mrg 500 1.1 mrg return g_timer->cond_start (timevar); 501 1.1 mrg } 502 1.1 mrg 503 1.1 mrg /* See timevar_cond_start above. */ 504 1.1 mrg 505 1.1 mrg bool 506 1.1 mrg timer::cond_start (timevar_id_t timevar) 507 1.1 mrg { 508 1.1 mrg struct timevar_def *tv = &m_timevars[timevar]; 509 1.1 mrg 510 1.1 mrg /* Mark this timing variable as used. */ 511 1.1 mrg tv->used = 1; 512 1.1 mrg 513 1.1 mrg if (tv->standalone) 514 1.1 mrg return true; /* The timevar is already running. */ 515 1.1 mrg 516 1.1 mrg /* Don't allow the same timing variable 517 1.1 mrg to be unconditionally started more than once. */ 518 1.1 mrg tv->standalone = 1; 519 1.1 mrg 520 1.1 mrg get_time (&tv->start_time); 521 1.1 mrg return false; /* The timevar was not already running. */ 522 1.1 mrg } 523 1.1 mrg 524 1.1 mrg /* Conditionally stop timing TIMEVAR. The RUNNING parameter must come 525 1.1 mrg from the return value of a dynamically matching timevar_cond_start. 526 1.1 mrg If the timer had already been RUNNING, do nothing. Otherwise, time 527 1.1 mrg elapsed since timevar_cond_start was called is attributed to it. */ 528 1.1 mrg 529 1.1 mrg void 530 1.1 mrg timevar_cond_stop (timevar_id_t timevar, bool running) 531 1.1 mrg { 532 1.1 mrg if (!g_timer || running) 533 1.1 mrg return; 534 1.1 mrg 535 1.1 mrg g_timer->cond_stop (timevar); 536 1.1 mrg } 537 1.1 mrg 538 1.1 mrg /* See timevar_cond_stop above. */ 539 1.1 mrg 540 1.1 mrg void 541 1.1 mrg timer::cond_stop (timevar_id_t timevar) 542 1.1 mrg { 543 1.1 mrg struct timevar_def *tv; 544 1.1 mrg struct timevar_time_def now; 545 1.1 mrg 546 1.1 mrg tv = &m_timevars[timevar]; 547 1.1 mrg 548 1.1 mrg /* TIMEVAR must have been started via timevar_cond_start. */ 549 1.1 mrg gcc_assert (tv->standalone); 550 1.1 mrg tv->standalone = 0; /* Enable a restart. */ 551 1.1 mrg 552 1.1 mrg get_time (&now); 553 1.1 mrg timevar_accumulate (&tv->elapsed, &tv->start_time, &now); 554 1.1 mrg } 555 1.1 mrg 556 1.1 mrg /* Push the named item onto the timing stack. */ 557 1.1 mrg 558 1.1 mrg void 559 1.1 mrg timer::push_client_item (const char *item_name) 560 1.1 mrg { 561 1.1 mrg gcc_assert (item_name); 562 1.1 mrg 563 1.1 mrg /* Lazily create the named_items instance. */ 564 1.1 mrg if (!m_jit_client_items) 565 1.1 mrg m_jit_client_items = new named_items (this); 566 1.1 mrg 567 1.1 mrg m_jit_client_items->push (item_name); 568 1.1 mrg } 569 1.1 mrg 570 1.1 mrg /* Pop the top-most client item from the timing stack. */ 571 1.1 mrg 572 1.1 mrg void 573 1.1 mrg timer::pop_client_item () 574 1.1 mrg { 575 1.1 mrg gcc_assert (m_jit_client_items); 576 1.1 mrg m_jit_client_items->pop (); 577 1.1 mrg } 578 1.1 mrg 579 1.1 mrg /* Validate that phase times are consistent. */ 580 1.1 mrg 581 1.1 mrg void 582 1.1 mrg timer::validate_phases (FILE *fp) const 583 1.1 mrg { 584 1.1 mrg unsigned int /* timevar_id_t */ id; 585 1.1 mrg const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed; 586 1.1 mrg double phase_user = 0.0; 587 1.1 mrg double phase_sys = 0.0; 588 1.1 mrg double phase_wall = 0.0; 589 1.1 mrg size_t phase_ggc_mem = 0; 590 1.1 mrg static char phase_prefix[] = "phase "; 591 1.1 mrg const double tolerance = 1.000001; /* One part in a million. */ 592 1.1 mrg 593 1.1 mrg for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id) 594 1.1 mrg { 595 1.1 mrg const timevar_def *tv = &m_timevars[(timevar_id_t) id]; 596 1.1 mrg 597 1.1 mrg /* Don't evaluate timing variables that were never used. */ 598 1.1 mrg if (!tv->used) 599 1.1 mrg continue; 600 1.1 mrg 601 1.1 mrg if (startswith (tv->name, phase_prefix)) 602 1.1 mrg { 603 1.1 mrg phase_user += tv->elapsed.user; 604 1.1 mrg phase_sys += tv->elapsed.sys; 605 1.1 mrg phase_wall += tv->elapsed.wall; 606 1.1 mrg phase_ggc_mem += tv->elapsed.ggc_mem; 607 1.1 mrg } 608 1.1 mrg } 609 1.1 mrg 610 1.1 mrg if (phase_user > total->user * tolerance 611 1.1 mrg || phase_sys > total->sys * tolerance 612 1.1 mrg || phase_wall > total->wall * tolerance 613 1.1 mrg || phase_ggc_mem > total->ggc_mem * tolerance) 614 1.1 mrg { 615 1.1 mrg 616 1.1 mrg fprintf (fp, "Timing error: total of phase timers exceeds total time.\n"); 617 1.1 mrg if (phase_user > total->user) 618 1.1 mrg fprintf (fp, "user %24.18e > %24.18e\n", phase_user, total->user); 619 1.1 mrg if (phase_sys > total->sys) 620 1.1 mrg fprintf (fp, "sys %24.18e > %24.18e\n", phase_sys, total->sys); 621 1.1 mrg if (phase_wall > total->wall) 622 1.1 mrg fprintf (fp, "wall %24.18e > %24.18e\n", phase_wall, total->wall); 623 1.1 mrg if (phase_ggc_mem > total->ggc_mem) 624 1.1 mrg fprintf (fp, "ggc_mem %24lu > %24lu\n", (unsigned long)phase_ggc_mem, 625 1.1 mrg (unsigned long)total->ggc_mem); 626 1.1 mrg gcc_unreachable (); 627 1.1 mrg } 628 1.1 mrg } 629 1.1 mrg 630 1.1 mrg /* Helper function for timer::print. */ 631 1.1 mrg 632 1.1 mrg void 633 1.1 mrg timer::print_row (FILE *fp, 634 1.1 mrg const timevar_time_def *total, 635 1.1 mrg const char *name, const timevar_time_def &elapsed) 636 1.1 mrg { 637 1.1 mrg /* The timing variable name. */ 638 1.1 mrg fprintf (fp, " %-35s:", name); 639 1.1 mrg 640 1.1 mrg #ifdef HAVE_USER_TIME 641 1.1 mrg /* Print user-mode time for this process. */ 642 1.1 mrg fprintf (fp, "%7.2f (%3.0f%%)", 643 1.1 mrg elapsed.user, 644 1.1 mrg (total->user == 0 ? 0 : elapsed.user / total->user) * 100); 645 1.1 mrg #endif /* HAVE_USER_TIME */ 646 1.1 mrg 647 1.1 mrg #ifdef HAVE_SYS_TIME 648 1.1 mrg /* Print system-mode time for this process. */ 649 1.1 mrg fprintf (fp, "%7.2f (%3.0f%%)", 650 1.1 mrg elapsed.sys, 651 1.1 mrg (total->sys == 0 ? 0 : elapsed.sys / total->sys) * 100); 652 1.1 mrg #endif /* HAVE_SYS_TIME */ 653 1.1 mrg 654 1.1 mrg #ifdef HAVE_WALL_TIME 655 1.1 mrg /* Print wall clock time elapsed. */ 656 1.1 mrg fprintf (fp, "%7.2f (%3.0f%%)", 657 1.1 mrg elapsed.wall, 658 1.1 mrg (total->wall == 0 ? 0 : elapsed.wall / total->wall) * 100); 659 1.1 mrg #endif /* HAVE_WALL_TIME */ 660 1.1 mrg 661 1.1 mrg /* Print the amount of ggc memory allocated. */ 662 1.1 mrg fprintf (fp, PRsa (6) " (%3.0f%%)", 663 1.1 mrg SIZE_AMOUNT (elapsed.ggc_mem), 664 1.1 mrg (total->ggc_mem == 0 665 1.1 mrg ? 0 666 1.1 mrg : (float) elapsed.ggc_mem / total->ggc_mem) * 100); 667 1.1 mrg 668 1.1 mrg putc ('\n', fp); 669 1.1 mrg } 670 1.1 mrg 671 1.1 mrg /* Return whether ELAPSED is all zero. */ 672 1.1 mrg 673 1.1 mrg bool 674 1.1 mrg timer::all_zero (const timevar_time_def &elapsed) 675 1.1 mrg { 676 1.1 mrg const double tiny = 5e-3; 677 1.1 mrg return (elapsed.user < tiny 678 1.1 mrg && elapsed.sys < tiny 679 1.1 mrg && elapsed.wall < tiny 680 1.1 mrg && elapsed.ggc_mem < GGC_MEM_BOUND); 681 1.1 mrg } 682 1.1 mrg 683 1.1 mrg /* Summarize timing variables to FP. The timing variable TV_TOTAL has 684 1.1 mrg a special meaning -- it's considered to be the total elapsed time, 685 1.1 mrg for normalizing the others, and is displayed last. */ 686 1.1 mrg 687 1.1 mrg void 688 1.1 mrg timer::print (FILE *fp) 689 1.1 mrg { 690 1.1 mrg /* Only print stuff if we have some sort of time information. */ 691 1.1 mrg #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME) 692 1.1 mrg unsigned int /* timevar_id_t */ id; 693 1.1 mrg const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed; 694 1.1 mrg struct timevar_time_def now; 695 1.1 mrg 696 1.1 mrg /* Update timing information in case we're calling this from GDB. */ 697 1.1 mrg 698 1.1 mrg if (fp == 0) 699 1.1 mrg fp = stderr; 700 1.1 mrg 701 1.1 mrg /* What time is it? */ 702 1.1 mrg get_time (&now); 703 1.1 mrg 704 1.1 mrg /* If the stack isn't empty, attribute the current elapsed time to 705 1.1 mrg the old topmost element. */ 706 1.1 mrg if (m_stack) 707 1.1 mrg timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now); 708 1.1 mrg 709 1.1 mrg /* Reset the start time; from now on, time is attributed to 710 1.1 mrg TIMEVAR. */ 711 1.1 mrg m_start_time = now; 712 1.1 mrg 713 1.1 mrg fprintf (fp, "\n%-35s%16s%14s%14s%14s\n", "Time variable", "usr", "sys", 714 1.1 mrg "wall", "GGC"); 715 1.1 mrg if (m_jit_client_items) 716 1.1 mrg fputs ("GCC items:\n", fp); 717 1.1 mrg for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id) 718 1.1 mrg { 719 1.1 mrg const timevar_def *tv = &m_timevars[(timevar_id_t) id]; 720 1.1 mrg 721 1.1 mrg /* Don't print the total execution time here; that goes at the 722 1.1 mrg end. */ 723 1.1 mrg if ((timevar_id_t) id == TV_TOTAL) 724 1.1 mrg continue; 725 1.1 mrg 726 1.1 mrg /* Don't print timing variables that were never used. */ 727 1.1 mrg if (!tv->used) 728 1.1 mrg continue; 729 1.1 mrg 730 1.1 mrg bool any_children_with_time = false; 731 1.1 mrg if (tv->children) 732 1.1 mrg for (child_map_t::iterator i = tv->children->begin (); 733 1.1 mrg i != tv->children->end (); ++i) 734 1.1 mrg if (! all_zero ((*i).second)) 735 1.1 mrg { 736 1.1 mrg any_children_with_time = true; 737 1.1 mrg break; 738 1.1 mrg } 739 1.1 mrg 740 1.1 mrg /* Don't print timing variables if we're going to get a row of 741 1.1 mrg zeroes. Unless there are children with non-zero time. */ 742 1.1 mrg if (! any_children_with_time 743 1.1 mrg && all_zero (tv->elapsed)) 744 1.1 mrg continue; 745 1.1 mrg 746 1.1 mrg print_row (fp, total, tv->name, tv->elapsed); 747 1.1 mrg 748 1.1 mrg if (tv->children) 749 1.1 mrg for (child_map_t::iterator i = tv->children->begin (); 750 1.1 mrg i != tv->children->end (); ++i) 751 1.1 mrg { 752 1.1 mrg timevar_def *tv2 = (*i).first; 753 1.1 mrg /* Don't print timing variables if we're going to get a row of 754 1.1 mrg zeroes. */ 755 1.1 mrg if (! all_zero ((*i).second)) 756 1.1 mrg { 757 1.1 mrg char lname[256]; 758 1.1 mrg snprintf (lname, 256, "`- %s", tv2->name); 759 1.1 mrg print_row (fp, total, lname, (*i).second); 760 1.1 mrg } 761 1.1 mrg } 762 1.1 mrg } 763 1.1 mrg if (m_jit_client_items) 764 1.1 mrg m_jit_client_items->print (fp, total); 765 1.1 mrg 766 1.1 mrg /* Print total time. */ 767 1.1 mrg fprintf (fp, " %-35s:", "TOTAL"); 768 1.1 mrg #ifdef HAVE_USER_TIME 769 1.1 mrg fprintf (fp, "%7.2f ", total->user); 770 1.1 mrg #endif 771 1.1 mrg #ifdef HAVE_SYS_TIME 772 1.1 mrg fprintf (fp, "%8.2f ", total->sys); 773 1.1 mrg #endif 774 1.1 mrg #ifdef HAVE_WALL_TIME 775 1.1 mrg fprintf (fp, "%8.2f ", total->wall); 776 1.1 mrg #endif 777 1.1 mrg fprintf (fp, PRsa (7) "\n", SIZE_AMOUNT (total->ggc_mem)); 778 1.1 mrg 779 1.1 mrg if (CHECKING_P || flag_checking) 780 1.1 mrg fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n"); 781 1.1 mrg if (CHECKING_P) 782 1.1 mrg fprintf (fp, "Configure with --enable-checking=release to disable checks.\n"); 783 1.1 mrg #ifndef ENABLE_ASSERT_CHECKING 784 1.1 mrg fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n"); 785 1.1 mrg fprintf (fp, "Configure with --enable-checking=release to enable checks.\n"); 786 1.1 mrg #endif 787 1.1 mrg 788 1.1 mrg #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) 789 1.1 mrg || defined (HAVE_WALL_TIME) */ 790 1.1 mrg 791 1.1 mrg validate_phases (fp); 792 1.1 mrg } 793 1.1 mrg 794 1.1 mrg /* Get the name of the topmost item. For use by jit for validating 795 1.1 mrg inputs to gcc_jit_timer_pop. */ 796 1.1 mrg const char * 797 1.1 mrg timer::get_topmost_item_name () const 798 1.1 mrg { 799 1.1 mrg if (m_stack) 800 1.1 mrg return m_stack->timevar->name; 801 1.1 mrg else 802 1.1 mrg return NULL; 803 1.1 mrg } 804 1.1 mrg 805 1.1 mrg /* Prints a message to stderr stating that time elapsed in STR is 806 1.1 mrg TOTAL (given in microseconds). */ 807 1.1 mrg 808 1.1 mrg void 809 1.1 mrg print_time (const char *str, long total) 810 1.1 mrg { 811 1.1 mrg long all_time = get_run_time (); 812 1.1 mrg fprintf (stderr, 813 1.1 mrg "time in %s: %ld.%06ld (%ld%%)\n", 814 1.1 mrg str, total / 1000000, total % 1000000, 815 1.1 mrg all_time == 0 ? 0 816 1.1 mrg : (long) (((100.0 * (double) total) / (double) all_time) + .5)); 817 1.1 mrg } 818