* targhooks.c (default_unwind_emit, default_scalar_mode_supported_p): Use gcc_assert, gcc_unreachable & internal_error instead of abort. * timevar.c (timevar_push, timevar_pop, timevar_start, timevar_stop): Likewise. * toplev.c (default_pch_valid_p): Likewise. * tracer.c (tail_duplicate): Likewise. * tree-alias-common.c (get_alias_var_decl, get_values_from_constructor, create_alias_var, delete_alias_vars, empty_points_to_set, same_points_to_set, ptr_may_alias_var): Likewise. * tree.c (tree_size, make_node_stat, copy_node_stat, build_int_cst_wide, integer_all_onesp, list_length, chainon, tree_node_structure, type_contains_placeholder_p, substitute_in_expr, substitute_placeholder_in_expr, tabilize_reference_1, build0_stat, build1_stat, build2_stat, build3_stat, build4_stat, is_attribute_p, lookup_attribute, type_hash_canon, host_integerp, iterative_hash_expr, build_method_type_directly, decl_type_context, get_callee_fndecl, get_set_constructor_bits, build_vector_type_for_mode, int_cst_value, tree_fold_gcd): Likewise. * tree-cfg.c (create_bb, make_ctrl_stmt_edges, make_exit_edges, make_cond_expr_edges, group_case_labels, tree_merge_blocks, cleanup_control_expr_graph, find_taken_edge, find_taken_edge_switch_expr, phi_alternatives_equal, is_ctrl_altering_stmt, disband_implicit_edges, set_bb_for_stmt, stmt_for_bsi, tree_find_edge_insert_loc, bsi_insert_on_edge_immediate, tree_split_edge, tree_verify_flow_info, thread_jumps, tree_redirect_edge_and_branch, tree_flow_call_edges_add): Likewise. * tree-chrec.c (chrec_fold_poly_cst, chrec_fold_plus_poly_poly, chrec_fold_multiply_poly_poly): Likewise. * tree-complex.c (extract_component, expand_complex_division, expand_complex_comparison, expand_complex_operations_1, build_replicated_const, expand_vector_operations_1): Likewise. * tree-data-ref.c (tree_fold_bezout, build_classic_dist_vector, build_classic_dir_vector): Likewise. * tree-dfa.c (compute_immediate_uses_for_phi, compute_immediate_uses_for_stmt, create_var_ann, create_stmt_ann, create_tree_ann, collect_dfa_stats, get_virtual_var): Likewise. * tree-dump.c (dequeue_and_dump): Likewise. * tree-eh.c (record_stmt_eh_region, add_stmt_to_eh_region, record_in_finally_tree, replace_goto_queue_1, maybe_record_in_goto_queue, verify_norecord_switch_expr, do_return_redirection): Likewise. * tree-if-conv.c (tree_if_convert_stmt, tree_if_convert_cond_expr, add_to_dst_predicate_list, find_phi_replacement_condition, replace_phi_with_cond_modify_expr, get_loop_body_in_if_conv_order): Likewise. * tree-inline.c (remap_decl, remap_type, remap_decls, copy_body_r, initialize_inlined_parameters, declare_return_variable, estimate_num_insns_1, expand_call_inline, expand_calls_inline, optimize_inline_calls, copy_tree_r): Likewise. * tree-into-ssa.c (rewrite_initialize_block_local_data, rewrite_stmt, ssa_rewrite_stmt, rewrite_into_ssa): Likewise. * tree-iterator.c (alloc_stmt_list, tsi_link_before, tsi_link_after, tsi_split_statement_list_after, tsi_split_statement_list_before): Likewise. * tree-mudflap.c (mf_varname_tree): Likewise. * tree-nested.c (create_tmp_var_for, lookup_field_for_decl, lookup_tramp_for_decl, convert_all_function_calls): Likewise. * tree-optimize.c (tree_rest_of_compilation): Likewise. * tree-outof-ssa.c (create_temp, eliminate_build, eliminate_phi, coalesce_abnormal_edges, coalesce_ssa_name, eliminate_virtual_phis, free_temp_expr_table, add_dependance, finish_expr, rewrite_trees): Likewise. * tree-phinodes.c (resize_phi_node, add_phi_arg, remove_all_phi_nodes_for): Likewise. * tree-pretty-print.c (op_prio, print_call_name): Likewise. * tree-profile.c (tree_gen_interval_profiler, tree_gen_pow2_profiler, tree_gen_one_value_profiler, tree_gen_const_delta_profiler): Likewise. * tree-sra.c (type_can_instantiate_all_elements, sra_hash_tree, sra_elt_eq, sra_walk_expr, instantiate_missing_elements, generate_one_element_ref, generate_element_copy, generate_element_zero, scalarize_copy, scalarize_init, scalarize_ldst): Likewise. * tree-ssa-alias.c (delete_alias_info, group_aliases, may_alias_p, add_may_alias, add_pointed_to_expr, add_pointed_to_var, collect_points_to_info_r, get_tmt_for, get_ptr_info): Likewise. * tree-ssa.c (walk_use_def_chains, check_phi_redundancy): Likewise. * tree-ssa-ccp.c (dump_lattice_value, get_default_value, get_value, set_lattice_value, likely_value, ccp_visit_phi_node, visit_assignment, widen_bitfield, ccp_fold_builtin): Likewise. * tree-ssa-copy.c (may_propagate_copy, merge_alias_info, replace_exp_1, propagate_tree_value): Likewise. * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Likewise. * tree-ssa-dce.c (set_control_dependence_map_bit, find_control_dependence, find_pdom, mark_operand_necessary, mark_stmt_if_obviously_necessary, mark_control_dependent_edges_necessary, remove_dead_stmt): Likewise. * tree-ssa-dom.c (dom_opt_initialize_block_local_data, simplify_switch_and_lookup_avail_expr, cprop_into_successor_phis, eliminate_redundant_computations, avail_expr_eq): Likewise. * tree-ssa-dse.c (fix_stmt_v_may_defs): Likewise. * tree-ssa-loop-ch.c (should_duplicate_loop_header_p, duplicate_blocks): Likewise. * tree-ssa-loop-im.c (for_each_index, set_level, is_call_clobbered_ref): Likewise. * tree-ssa-loop-ivopts.c (dump_use, divide, stmt_after_ip_normal_pos, stmt_after_increment, set_iv, contains_abnormal_ssa_name_p, find_interesting_uses_outer_or_nonlin, add_derived_ivs_candidates, peel_address, ptr_difference_cost, may_replace_final_value, determine_use_iv_cost, rewrite_use_nonlinear_expr, rewrite_use_outer, rewrite_use, rewrite_uses): Likewise. * tree-ssa-loop-manip.c (rewrite_into_loop_closed_ssa, check_loop_closed_ssa_use): Likewise. * tree-ssanames.c (make_ssa_name): Likewise. * tree-ssa-operands.c (finalize_ssa_defs, finalize_ssa_uses, finalize_ssa_v_must_defs, finalize_ssa_stmt_operands, get_stmt_operands, get_expr_operands, get_asm_expr_operands, get_indirect_ref_operands, add_stmt_operand): Likewise. * tree-ssa-pre.c (value_exists_in_set_bitmap, value_remove_from_set_bitmap, bitmap_insert_into_set, insert_into_set, phi_translate, valid_in_set, compute_antic, find_or_generate_expression, create_expression_by_pieces, insert_aux, create_value_expr_from, eliminate): Likewise. * tree-ssa-propagate.c (cfg_blocks_get): Likewise. * tree-ssa-threadupdate.c (remove_last_stmt_and_useless_edges): Likewise. * tree-tailcall.c (independent_of_stmt_p, adjust_return_value, eliminate_tail_call): Likewise. * tree-vectorizer.c (vect_create_index_for_array_ref, vect_align_data_ref, vect_create_data_ref, vect_create_destination_var, vect_get_vec_def_for_operand, vect_finish_stmt_generation, vect_transform_stmt, vect_transform_loop_bound, vect_transform_loop, vect_analyze_operations): Likewise. * tree-vn.c (vn_compute, set_value_handle, get_value_handle): Likewise. * tree-flow-inline.h (var_ann, get_var_ann, get_def_from_ptr, get_use_op_ptr, immediate_use, phi_ssa_name_p, bsi_start, bsi_after_labels, bsi_last): Likewise. * tree-ssa-live.c (var_union, change_partition_var, create_ssa_var_map, calculate_live_on_entry, root_var_init, type_var_init, add_coalesce, sort_coalesce_list, pop_best_coalesce): Likewise. * tree-ssa-live.h (partition_is_global, live_entry_blocks, tpa_find_tree): Likewise. (register_ssa_partition_check): Declare. (register_ssa_partition): use it. * tree-ssa-live.c: Include errors.h. (register_ssa_partition_check): New. * tree-ssa-operands.c: Include errors.h. * Makefile.in (tree-ssa-operands.o): Depend on errors.h. Co-Authored-By: Nathan Sidwell <nathan@codesourcery.com> From-SVN: r87223
515 lines
14 KiB
C
515 lines
14 KiB
C
/* Timing variables for measuring compiler performance.
|
|
Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc.
|
|
Contributed by Alex Samuel <samuel@codesourcery.com>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 2, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING. If not, write to the Free
|
|
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|
02111-1307, USA. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#ifdef HAVE_SYS_TIMES_H
|
|
# include <sys/times.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_RESOURCE_H
|
|
#include <sys/resource.h>
|
|
#endif
|
|
#include "coretypes.h"
|
|
#include "tm.h"
|
|
#include "intl.h"
|
|
#include "rtl.h"
|
|
#include "toplev.h"
|
|
|
|
#ifndef HAVE_CLOCK_T
|
|
typedef int clock_t;
|
|
#endif
|
|
|
|
#ifndef HAVE_STRUCT_TMS
|
|
struct tms
|
|
{
|
|
clock_t tms_utime;
|
|
clock_t tms_stime;
|
|
clock_t tms_cutime;
|
|
clock_t tms_cstime;
|
|
};
|
|
#endif
|
|
|
|
#ifndef RUSAGE_SELF
|
|
# define RUSAGE_SELF 0
|
|
#endif
|
|
|
|
/* Calculation of scale factor to convert ticks to microseconds.
|
|
We mustn't use CLOCKS_PER_SEC except with clock(). */
|
|
#if HAVE_SYSCONF && defined _SC_CLK_TCK
|
|
# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
|
|
#else
|
|
# ifdef CLK_TCK
|
|
# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
|
|
# else
|
|
# ifdef HZ
|
|
# define TICKS_PER_SECOND HZ /* traditional UNIX */
|
|
# else
|
|
# define TICKS_PER_SECOND 100 /* often the correct value */
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
/* Prefer times to getrusage to clock (each gives successively less
|
|
information). */
|
|
#ifdef HAVE_TIMES
|
|
# if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
|
|
extern clock_t times (struct tms *);
|
|
# endif
|
|
# define USE_TIMES
|
|
# define HAVE_USER_TIME
|
|
# define HAVE_SYS_TIME
|
|
# define HAVE_WALL_TIME
|
|
#else
|
|
#ifdef HAVE_GETRUSAGE
|
|
# if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
|
|
extern int getrusage (int, struct rusage *);
|
|
# endif
|
|
# define USE_GETRUSAGE
|
|
# define HAVE_USER_TIME
|
|
# define HAVE_SYS_TIME
|
|
#else
|
|
#ifdef HAVE_CLOCK
|
|
# if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
|
|
extern clock_t clock (void);
|
|
# endif
|
|
# define USE_CLOCK
|
|
# define HAVE_USER_TIME
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
/* libc is very likely to have snuck a call to sysconf() into one of
|
|
the underlying constants, and that can be very slow, so we have to
|
|
precompute them. Whose wonderful idea was it to make all those
|
|
_constants_ variable at run time, anyway? */
|
|
#ifdef USE_TIMES
|
|
static double ticks_to_msec;
|
|
#define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
|
|
#endif
|
|
|
|
#ifdef USE_CLOCK
|
|
static double clocks_to_msec;
|
|
#define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
|
|
#endif
|
|
|
|
#include "flags.h"
|
|
#include "timevar.h"
|
|
|
|
static bool timevar_enable;
|
|
|
|
/* See timevar.h for an explanation of timing variables. */
|
|
|
|
/* A timing variable. */
|
|
|
|
struct timevar_def
|
|
{
|
|
/* Elapsed time for this variable. */
|
|
struct timevar_time_def elapsed;
|
|
|
|
/* If this variable is timed independently of the timing stack,
|
|
using timevar_start, this contains the start time. */
|
|
struct timevar_time_def start_time;
|
|
|
|
/* The name of this timing variable. */
|
|
const char *name;
|
|
|
|
/* Nonzero if this timing variable is running as a standalone
|
|
timer. */
|
|
unsigned standalone : 1;
|
|
|
|
/* Nonzero if this timing variable was ever started or pushed onto
|
|
the timing stack. */
|
|
unsigned used : 1;
|
|
};
|
|
|
|
/* An element on the timing stack. Elapsed time is attributed to the
|
|
topmost timing variable on the stack. */
|
|
|
|
struct timevar_stack_def
|
|
{
|
|
/* The timing variable at this stack level. */
|
|
struct timevar_def *timevar;
|
|
|
|
/* The next lower timing variable context in the stack. */
|
|
struct timevar_stack_def *next;
|
|
};
|
|
|
|
/* Declared timing variables. Constructed from the contents of
|
|
timevar.def. */
|
|
static struct timevar_def timevars[TIMEVAR_LAST];
|
|
|
|
/* The top of the timing stack. */
|
|
static struct timevar_stack_def *stack;
|
|
|
|
/* A list of unused (i.e. allocated and subsequently popped)
|
|
timevar_stack_def instances. */
|
|
static struct timevar_stack_def *unused_stack_instances;
|
|
|
|
/* The time at which the topmost element on the timing stack was
|
|
pushed. Time elapsed since then is attributed to the topmost
|
|
element. */
|
|
static struct timevar_time_def start_time;
|
|
|
|
static void get_time (struct timevar_time_def *);
|
|
static void timevar_accumulate (struct timevar_time_def *,
|
|
struct timevar_time_def *,
|
|
struct timevar_time_def *);
|
|
|
|
/* Fill the current times into TIME. The definition of this function
|
|
also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
|
|
HAVE_WALL_TIME macros. */
|
|
|
|
static void
|
|
get_time (struct timevar_time_def *now)
|
|
{
|
|
now->user = 0;
|
|
now->sys = 0;
|
|
now->wall = 0;
|
|
|
|
if (!timevar_enable)
|
|
return;
|
|
|
|
{
|
|
#ifdef USE_TIMES
|
|
struct tms tms;
|
|
now->wall = times (&tms) * ticks_to_msec;
|
|
now->user = tms.tms_utime * ticks_to_msec;
|
|
now->sys = tms.tms_stime * ticks_to_msec;
|
|
#endif
|
|
#ifdef USE_GETRUSAGE
|
|
struct rusage rusage;
|
|
getrusage (RUSAGE_SELF, &rusage);
|
|
now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
|
|
now->sys = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
|
|
#endif
|
|
#ifdef USE_CLOCK
|
|
now->user = clock () * clocks_to_msec;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* Add the difference between STOP_TIME and START_TIME to TIMER. */
|
|
|
|
static void
|
|
timevar_accumulate (struct timevar_time_def *timer,
|
|
struct timevar_time_def *start_time,
|
|
struct timevar_time_def *stop_time)
|
|
{
|
|
timer->user += stop_time->user - start_time->user;
|
|
timer->sys += stop_time->sys - start_time->sys;
|
|
timer->wall += stop_time->wall - start_time->wall;
|
|
}
|
|
|
|
/* Initialize timing variables. */
|
|
|
|
void
|
|
timevar_init (void)
|
|
{
|
|
timevar_enable = true;
|
|
|
|
/* Zero all elapsed times. */
|
|
memset (timevars, 0, sizeof (timevars));
|
|
|
|
/* Initialize the names of timing variables. */
|
|
#define DEFTIMEVAR(identifier__, name__) \
|
|
timevars[identifier__].name = name__;
|
|
#include "timevar.def"
|
|
#undef DEFTIMEVAR
|
|
|
|
#ifdef USE_TIMES
|
|
ticks_to_msec = TICKS_TO_MSEC;
|
|
#endif
|
|
#ifdef USE_CLOCK
|
|
clocks_to_msec = CLOCKS_TO_MSEC;
|
|
#endif
|
|
}
|
|
|
|
/* Push TIMEVAR onto the timing stack. No further elapsed time is
|
|
attributed to the previous topmost timing variable on the stack;
|
|
subsequent elapsed time is attributed to TIMEVAR, until it is
|
|
popped or another element is pushed on top.
|
|
|
|
TIMEVAR cannot be running as a standalone timer. */
|
|
|
|
void
|
|
timevar_push (timevar_id_t timevar)
|
|
{
|
|
struct timevar_def *tv = &timevars[timevar];
|
|
struct timevar_stack_def *context;
|
|
struct timevar_time_def now;
|
|
|
|
if (!timevar_enable)
|
|
return;
|
|
|
|
/* Mark this timing variable as used. */
|
|
tv->used = 1;
|
|
|
|
/* Can't push a standalone timer. */
|
|
gcc_assert (!tv->standalone);
|
|
|
|
/* What time is it? */
|
|
get_time (&now);
|
|
|
|
/* If the stack isn't empty, attribute the current elapsed time to
|
|
the old topmost element. */
|
|
if (stack)
|
|
timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
|
|
|
|
/* Reset the start time; from now on, time is attributed to
|
|
TIMEVAR. */
|
|
start_time = now;
|
|
|
|
/* See if we have a previously-allocated stack instance. If so,
|
|
take it off the list. If not, malloc a new one. */
|
|
if (unused_stack_instances != NULL)
|
|
{
|
|
context = unused_stack_instances;
|
|
unused_stack_instances = unused_stack_instances->next;
|
|
}
|
|
else
|
|
context = xmalloc (sizeof (struct timevar_stack_def));
|
|
|
|
/* Fill it in and put it on the stack. */
|
|
context->timevar = tv;
|
|
context->next = stack;
|
|
stack = context;
|
|
}
|
|
|
|
/* Pop the topmost timing variable element off the timing stack. The
|
|
popped variable must be TIMEVAR. Elapsed time since the that
|
|
element was pushed on, or since it was last exposed on top of the
|
|
stack when the element above it was popped off, is credited to that
|
|
timing variable. */
|
|
|
|
void
|
|
timevar_pop (timevar_id_t timevar)
|
|
{
|
|
struct timevar_time_def now;
|
|
struct timevar_stack_def *popped = stack;
|
|
|
|
if (!timevar_enable)
|
|
return;
|
|
|
|
gcc_assert (&timevars[timevar] == stack->timevar);
|
|
|
|
/* What time is it? */
|
|
get_time (&now);
|
|
|
|
/* Attribute the elapsed time to the element we're popping. */
|
|
timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
|
|
|
|
/* Reset the start time; from now on, time is attributed to the
|
|
element just exposed on the stack. */
|
|
start_time = now;
|
|
|
|
/* Take the item off the stack. */
|
|
stack = stack->next;
|
|
|
|
/* Don't delete the stack element; instead, add it to the list of
|
|
unused elements for later use. */
|
|
popped->next = unused_stack_instances;
|
|
unused_stack_instances = popped;
|
|
}
|
|
|
|
/* Start timing TIMEVAR independently of the timing stack. Elapsed
|
|
time until timevar_stop is called for the same timing variable is
|
|
attributed to TIMEVAR. */
|
|
|
|
void
|
|
timevar_start (timevar_id_t timevar)
|
|
{
|
|
struct timevar_def *tv = &timevars[timevar];
|
|
|
|
if (!timevar_enable)
|
|
return;
|
|
|
|
/* Mark this timing variable as used. */
|
|
tv->used = 1;
|
|
|
|
/* Don't allow the same timing variable to be started more than
|
|
once. */
|
|
gcc_assert (!tv->standalone);
|
|
tv->standalone = 1;
|
|
|
|
get_time (&tv->start_time);
|
|
}
|
|
|
|
/* Stop timing TIMEVAR. Time elapsed since timevar_start was called
|
|
is attributed to it. */
|
|
|
|
void
|
|
timevar_stop (timevar_id_t timevar)
|
|
{
|
|
struct timevar_def *tv = &timevars[timevar];
|
|
struct timevar_time_def now;
|
|
|
|
if (!timevar_enable)
|
|
return;
|
|
|
|
/* TIMEVAR must have been started via timevar_start. */
|
|
gcc_assert (tv->standalone);
|
|
|
|
get_time (&now);
|
|
timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
|
|
}
|
|
|
|
/* Fill the elapsed time for TIMEVAR into ELAPSED. Returns
|
|
update-to-date information even if TIMEVAR is currently running. */
|
|
|
|
void
|
|
timevar_get (timevar_id_t timevar, struct timevar_time_def *elapsed)
|
|
{
|
|
struct timevar_def *tv = &timevars[timevar];
|
|
struct timevar_time_def now;
|
|
|
|
*elapsed = tv->elapsed;
|
|
|
|
/* Is TIMEVAR currently running as a standalone timer? */
|
|
if (tv->standalone)
|
|
{
|
|
get_time (&now);
|
|
timevar_accumulate (elapsed, &tv->start_time, &now);
|
|
}
|
|
/* Or is TIMEVAR at the top of the timer stack? */
|
|
else if (stack->timevar == tv)
|
|
{
|
|
get_time (&now);
|
|
timevar_accumulate (elapsed, &start_time, &now);
|
|
}
|
|
}
|
|
|
|
/* Summarize timing variables to FP. The timing variable TV_TOTAL has
|
|
a special meaning -- it's considered to be the total elapsed time,
|
|
for normalizing the others, and is displayed last. */
|
|
|
|
void
|
|
timevar_print (FILE *fp)
|
|
{
|
|
/* Only print stuff if we have some sort of time information. */
|
|
#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
|
|
unsigned int /* timevar_id_t */ id;
|
|
struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
|
|
struct timevar_time_def now;
|
|
|
|
if (!timevar_enable)
|
|
return;
|
|
|
|
/* Update timing information in case we're calling this from GDB. */
|
|
|
|
if (fp == 0)
|
|
fp = stderr;
|
|
|
|
/* What time is it? */
|
|
get_time (&now);
|
|
|
|
/* If the stack isn't empty, attribute the current elapsed time to
|
|
the old topmost element. */
|
|
if (stack)
|
|
timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
|
|
|
|
/* Reset the start time; from now on, time is attributed to
|
|
TIMEVAR. */
|
|
start_time = now;
|
|
|
|
fputs (_("\nExecution times (seconds)\n"), fp);
|
|
for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
|
|
{
|
|
struct timevar_def *tv = &timevars[(timevar_id_t) id];
|
|
const double tiny = 5e-3;
|
|
|
|
/* Don't print the total execution time here; that goes at the
|
|
end. */
|
|
if ((timevar_id_t) id == TV_TOTAL)
|
|
continue;
|
|
|
|
/* Don't print timing variables that were never used. */
|
|
if (!tv->used)
|
|
continue;
|
|
|
|
/* Don't print timing variables if we're going to get a row of
|
|
zeroes. */
|
|
if (tv->elapsed.user < tiny
|
|
&& tv->elapsed.sys < tiny
|
|
&& tv->elapsed.wall < tiny)
|
|
continue;
|
|
|
|
/* The timing variable name. */
|
|
fprintf (fp, " %-22s:", tv->name);
|
|
|
|
#ifdef HAVE_USER_TIME
|
|
/* Print user-mode time for this process. */
|
|
fprintf (fp, "%7.2f (%2.0f%%) usr",
|
|
tv->elapsed.user,
|
|
(total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
|
|
#endif /* HAVE_USER_TIME */
|
|
|
|
#ifdef HAVE_SYS_TIME
|
|
/* Print system-mode time for this process. */
|
|
fprintf (fp, "%7.2f (%2.0f%%) sys",
|
|
tv->elapsed.sys,
|
|
(total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
|
|
#endif /* HAVE_SYS_TIME */
|
|
|
|
#ifdef HAVE_WALL_TIME
|
|
/* Print wall clock time elapsed. */
|
|
fprintf (fp, "%7.2f (%2.0f%%) wall",
|
|
tv->elapsed.wall,
|
|
(total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
|
|
#endif /* HAVE_WALL_TIME */
|
|
|
|
putc ('\n', fp);
|
|
}
|
|
|
|
/* Print total time. */
|
|
fputs (_(" TOTAL :"), fp);
|
|
#ifdef HAVE_USER_TIME
|
|
fprintf (fp, "%7.2f ", total->user);
|
|
#endif
|
|
#ifdef HAVE_SYS_TIME
|
|
fprintf (fp, "%7.2f ", total->sys);
|
|
#endif
|
|
#ifdef HAVE_WALL_TIME
|
|
fprintf (fp, "%7.2f\n", total->wall);
|
|
#endif
|
|
|
|
#ifdef ENABLE_CHECKING
|
|
fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
|
|
fprintf (fp, "Configure with --disable-checking to disable checks.\n");
|
|
#endif
|
|
|
|
#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
|
|
|| defined (HAVE_WALL_TIME) */
|
|
}
|
|
|
|
/* Prints a message to stderr stating that time elapsed in STR is
|
|
TOTAL (given in microseconds). */
|
|
|
|
void
|
|
print_time (const char *str, long total)
|
|
{
|
|
long all_time = get_run_time ();
|
|
fprintf (stderr,
|
|
_("time in %s: %ld.%06ld (%ld%%)\n"),
|
|
str, total / 1000000, total % 1000000,
|
|
all_time == 0 ? 0
|
|
: (long) (((100.0 * (double) total) / (double) all_time) + .5));
|
|
}
|