Refactoring of timevar API

gcc/ChangeLog:
	* main.c (main): Pass in NULL for toplev's external_timer.
	* timevar.c: Include coretypes.h.
	(class timer::named_items): New.
	(timer::named_items::named_items): New.
	(timer::named_items::~named_items): New.
	(timer::named_items::push): New.
	(timer::named_items::pop): New.
	(timer::named_items::print): New.
	(timer::timer): Initialize field "m_jit_client_items".
	(timer::~timer): New.
	(timer::push): Move bulk of implementation to...
	(timer::push_internal): ...here.  New function.
	(timer::pop): Move bulk of implementation to...
	(timer::pop_internal): ...here.  New function.
	(timer::push_client_item): New.
	(timer::pop_client_item): New.
	(timer::print_row): New function, taken from timer::print.
	(timer::print): Print "GCC items" header if we also have client
	items.  Move row-printing to timer::print_row.  Print any client
	items.
	(timer::get_topmost_item_name): New method.
	* timevar.def (TV_JIT_ACQUIRING_MUTEX): New.
	(TV_JIT_CLIENT_CODE): New.
	* timevar.h (timer::push_client_item): New declaration.
	(timer::pop_client_item): New declaration.
	(timer::get_topmost_item_name): New method.
	(timer::push_internal): New declaration.
	(timer::pop_internal): New declaration.
	(timer::print_row): New declaration.
	(timer::named_items): New declaration.
	(timer::m_jit_client_items): New field.
	(timer): Add friend class named_items.
	(auto_timevar::auto_timevar): Add timer param.
	(auto_timevar::~auto_timevar): Use field "m_timer".
	(auto_timevar::m_timer): New field.
	* toplev.c (initialize_rtl): Add g_timer as param when
	constructing auto_timevar instance.
	(toplev::toplev): Add "external_timer" param, and use it to
	initialize the "g_timer" global if non-NULL.
	(toplev::~toplev): If this created "g_timer", delete it.
	* toplev.h (toplev::toplev): Replace "use_TV_TOTAL" bool param
	with "external_timer" timer *.

gcc/jit/ChangeLog:
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_4): New.
	* docs/topics/contexts.rst (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY):
	We no longer show a profile.
	* docs/topics/index.rst (Topic Reference): Add performance.rst.
	* docs/topics/performance.rst: New file.
	* docs/_build/texinfo/libgccjit.texi: Regenerate.
	* jit-playback.c (gcc::jit::playback::context::compile): Add timer
	param when constructing the "toplev" instance.
	(gcc::jit::playback::context::acquire_mutex): Add timer param when
	constructing auto_timevar instance.
	(gcc::jit::playback::context::make_fake_args): If we have a timer,
	add "-ftime-report".
	(gcc::jit::playback::context::invoke_driver): Add timer param when
	constructing auto_timevar instance.
	(gcc::jit::playback::context::dlopen_built_dso): Likewise.
	* jit-playback.h (gcc::jit::playback::context::get_timer): New accessor.
	* jit-recording.c: Include timevar.h.
	(gcc::jit::recording::context::context): Initialize field "m_timer".
	* jit-recording.h: Add forward declaration of class timer.
	(gcc::jit::recording::context::set_timer): New method.
	(gcc::jit::recording::context::get_timer): New method.
	(gcc::jit::recording::context::m_timer): New field.
	* libgccjit++.h (gccjit::timer): New class.
	(gccjit::auto_time): New class.
	(gccjit::context::set_timer): New method.
	(gccjit::context::get_timer): New.
	(gccjit::timer::timer): New.
	(gccjit::timer::push): New.
	(gccjit::timer::pop): New.
	(timer::print): New.
	(timer::get_inner_timer): New.
	(timer::release): New.
	(auto_time::auto_time): New.
	(auto_time::~auto_time): New.
	* libgccjit.c: Include timevar.h.
	(struct gcc_jit_timer): New.
	(gcc_jit_timer_new): New function.
	(gcc_jit_timer_release): New function.
	(gcc_jit_context_set_timer): New function.
	(gcc_jit_context_get_timer): New function.
	(gcc_jit_timer_push): New function.
	(gcc_jit_timer_pop): New function.
	(gcc_jit_timer_print): New function.
	* libgccjit.h (LIBGCCJIT_HAVE_TIMING_API): New macro.
	(gcc_jit_timer): New typedef.
	(gcc_jit_timer_new): New function.
	(gcc_jit_timer_release): New function.
	(gcc_jit_context_set_timer): New function.
	(gcc_jit_context_get_timer): New function.
	(gcc_jit_timer_push): New function.
	(gcc_jit_timer_pop): New function.
	(gcc_jit_timer_print): New function.
	* libgccjit.map (LIBGCCJIT_ABI_4): New.
	(gcc_jit_timer_new): New function.
	(gcc_jit_timer_release): New function.
	(gcc_jit_context_set_timer): New function.
	(gcc_jit_context_get_timer): New function.
	(gcc_jit_timer_push): New function.
	(gcc_jit_timer_pop): New function.
	(gcc_jit_timer_print): New function.

gcc/testsuite/ChangeLog:
	* jit.dg/test-benchmark.c (test_jit): Add param "timer" and use
	it to push/pop timing items.
	(main): For each optimization level, create a gcc_jit_timer, and
	time all of the iteration within that level cumulatively.
	* jit.dg/test-error-gcc_jit_timer_pop-mismatch.c: New test case.
	* jit.dg/test-error-gcc_jit_timer_pop-too-many.c: New test case.

From-SVN: r226530
This commit is contained in:
David Malcolm 2015-08-03 20:14:21 +00:00 committed by David Malcolm
parent ef9da28d8f
commit afed345982
25 changed files with 1667 additions and 320 deletions

View File

@ -1,3 +1,48 @@
2015-08-03 David Malcolm <dmalcolm@redhat.com>
* main.c (main): Pass in NULL for toplev's external_timer.
* timevar.c: Include coretypes.h.
(class timer::named_items): New.
(timer::named_items::named_items): New.
(timer::named_items::~named_items): New.
(timer::named_items::push): New.
(timer::named_items::pop): New.
(timer::named_items::print): New.
(timer::timer): Initialize field "m_jit_client_items".
(timer::~timer): New.
(timer::push): Move bulk of implementation to...
(timer::push_internal): ...here. New function.
(timer::pop): Move bulk of implementation to...
(timer::pop_internal): ...here. New function.
(timer::push_client_item): New.
(timer::pop_client_item): New.
(timer::print_row): New function, taken from timer::print.
(timer::print): Print "GCC items" header if we also have client
items. Move row-printing to timer::print_row. Print any client
items.
(timer::get_topmost_item_name): New method.
* timevar.def (TV_JIT_ACQUIRING_MUTEX): New.
(TV_JIT_CLIENT_CODE): New.
* timevar.h (timer::push_client_item): New declaration.
(timer::pop_client_item): New declaration.
(timer::get_topmost_item_name): New method.
(timer::push_internal): New declaration.
(timer::pop_internal): New declaration.
(timer::print_row): New declaration.
(timer::named_items): New declaration.
(timer::m_jit_client_items): New field.
(timer): Add friend class named_items.
(auto_timevar::auto_timevar): Add timer param.
(auto_timevar::~auto_timevar): Use field "m_timer".
(auto_timevar::m_timer): New field.
* toplev.c (initialize_rtl): Add g_timer as param when
constructing auto_timevar instance.
(toplev::toplev): Add "external_timer" param, and use it to
initialize the "g_timer" global if non-NULL.
(toplev::~toplev): If this created "g_timer", delete it.
* toplev.h (toplev::toplev): Replace "use_TV_TOTAL" bool param
with "external_timer" timer *.
2015-08-03 Alexander Basov <coohpt@gmail.com>
PR middle-end/64744

View File

@ -1,3 +1,66 @@
2015-08-03 David Malcolm <dmalcolm@redhat.com>
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_4): New.
* docs/topics/contexts.rst (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY):
We no longer show a profile.
* docs/topics/index.rst (Topic Reference): Add performance.rst.
* docs/topics/performance.rst: New file.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* jit-playback.c (gcc::jit::playback::context::compile): Add timer
param when constructing the "toplev" instance.
(gcc::jit::playback::context::acquire_mutex): Add timer param when
constructing auto_timevar instance.
(gcc::jit::playback::context::make_fake_args): If we have a timer,
add "-ftime-report".
(gcc::jit::playback::context::invoke_driver): Add timer param when
constructing auto_timevar instance.
(gcc::jit::playback::context::dlopen_built_dso): Likewise.
* jit-playback.h (gcc::jit::playback::context::get_timer): New accessor.
* jit-recording.c: Include timevar.h.
(gcc::jit::recording::context::context): Initialize field "m_timer".
* jit-recording.h: Add forward declaration of class timer.
(gcc::jit::recording::context::set_timer): New method.
(gcc::jit::recording::context::get_timer): New method.
(gcc::jit::recording::context::m_timer): New field.
* libgccjit++.h (gccjit::timer): New class.
(gccjit::auto_time): New class.
(gccjit::context::set_timer): New method.
(gccjit::context::get_timer): New.
(gccjit::timer::timer): New.
(gccjit::timer::push): New.
(gccjit::timer::pop): New.
(timer::print): New.
(timer::get_inner_timer): New.
(timer::release): New.
(auto_time::auto_time): New.
(auto_time::~auto_time): New.
* libgccjit.c: Include timevar.h.
(struct gcc_jit_timer): New.
(gcc_jit_timer_new): New function.
(gcc_jit_timer_release): New function.
(gcc_jit_context_set_timer): New function.
(gcc_jit_context_get_timer): New function.
(gcc_jit_timer_push): New function.
(gcc_jit_timer_pop): New function.
(gcc_jit_timer_print): New function.
* libgccjit.h (LIBGCCJIT_HAVE_TIMING_API): New macro.
(gcc_jit_timer): New typedef.
(gcc_jit_timer_new): New function.
(gcc_jit_timer_release): New function.
(gcc_jit_context_set_timer): New function.
(gcc_jit_context_get_timer): New function.
(gcc_jit_timer_push): New function.
(gcc_jit_timer_pop): New function.
(gcc_jit_timer_print): New function.
* libgccjit.map (LIBGCCJIT_ABI_4): New.
(gcc_jit_timer_new): New function.
(gcc_jit_timer_release): New function.
(gcc_jit_context_set_timer): New function.
(gcc_jit_context_get_timer): New function.
(gcc_jit_timer_push): New function.
(gcc_jit_timer_pop): New function.
(gcc_jit_timer_print): New function.
2015-07-23 David Malcolm <dmalcolm@redhat.com>
* jit-playback.c (invoke_driver): Convert local "argvec"

File diff suppressed because it is too large Load Diff

View File

@ -107,3 +107,24 @@ entrypoints:
* :func:`gcc_jit_case_as_object`
* :func:`gcc_jit_context_new_case`
.. _LIBGCCJIT_ABI_4:
``LIBGCCJIT_ABI_4``
-------------------
``LIBGCCJIT_ABI_4`` covers the addition of timers via API
entrypoints:
* :func:`gcc_jit_context_get_timer`
* :func:`gcc_jit_context_set_timer`
* :func:`gcc_jit_timer_new`
* :func:`gcc_jit_timer_release`
* :func:`gcc_jit_timer_push`
* :func:`gcc_jit_timer_pop`
* :func:`gcc_jit_timer_print`

View File

@ -430,8 +430,7 @@ Boolean options
.. macro:: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY
If true, :func:`gcc_jit_context_compile` will print information to stderr
on the actions it is performing, followed by a profile showing
the time taken and memory usage of each phase.
on the actions it is performing.
.. macro:: GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING

View File

@ -29,3 +29,4 @@ Topic Reference
locations.rst
compilation.rst
compatibility.rst
performance.rst

View File

@ -0,0 +1,240 @@
.. Copyright (C) 2015 Free Software Foundation, Inc.
Originally contributed by David Malcolm <dmalcolm@redhat.com>
This 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see
<http://www.gnu.org/licenses/>.
.. default-domain:: c
Performance
===========
The timing API
--------------
As of GCC 6, libgccjit exposes a timing API, for printing reports on
how long was spent in different parts of code.
You can create a :c:type:`gcc_jit_timer` instance, which will
measure time spent since its creation. The timer maintains a stack
of "timer items": as control flow moves through your code, you can push
and pop named items relating to your code onto the stack, and the timer
will account the time spent accordingly.
You can also asssociate a timer with a :c:type:`gcc_jit_context`, in
which case the time spent inside compilation will be subdivided.
For example, the following code uses a timer, recording client items
"create_code", "compile", and "running code":
.. code-block:: c
/* Create a timer. */
gcc_jit_timer *timer = gcc_jit_timer_new ();
if (!timer)
{
error ("gcc_jit_timer_new failed");
return -1;
}
/* Let's repeatedly compile and run some code, accumulating it
all into the timer. */
for (int i = 0; i < num_iterations; i++)
{
/* Create a context and associate it with the timer. */
gcc_jit_context *ctxt = gcc_jit_context_acquire ();
if (!ctxt)
{
error ("gcc_jit_context_acquire failed");
return -1;
}
gcc_jit_context_set_timer (ctxt, timer);
/* Populate the context, timing it as client item "create_code". */
gcc_jit_timer_push (timer, "create_code");
create_code (ctxt);
gcc_jit_timer_pop (timer, "create_code");
/* Compile the context, timing it as client item "compile". */
gcc_jit_timer_push (timer, "compile");
result = gcc_jit_context_compile (ctxt);
gcc_jit_timer_pop (timer, "compile");
/* Run the generated code, timing it as client item "running code". */
gcc_jit_timer_push (timer, "running code");
run_the_code (ctxt, result);
gcc_jit_timer_pop (timer, "running code");
/* Clean up. */
gcc_jit_context_release (ctxt);
gcc_jit_result_release (result);
}
/* Print the accumulated timings. */
gcc_jit_timer_print (timer, stderr);
gcc_jit_timer_release (timer);
giving output like this, showing the internal GCC items at the top, then
client items, then the total::
Execution times (seconds)
GCC items:
phase setup : 0.29 (14%) usr 0.00 ( 0%) sys 0.32 ( 5%) wall 10661 kB (50%) ggc
phase parsing : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 653 kB ( 3%) ggc
phase finalize : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
dump files : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc
callgraph construction : 0.02 ( 1%) usr 0.01 ( 6%) sys 0.01 ( 0%) wall 242 kB ( 1%) ggc
callgraph optimization : 0.03 ( 2%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 142 kB ( 1%) ggc
trivially dead code : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
df scan insns : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 9 kB ( 0%) ggc
df live regs : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc
inline parameters : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 82 kB ( 0%) ggc
tree CFG cleanup : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
tree PHI insertion : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 64 kB ( 0%) ggc
tree SSA other : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 18 kB ( 0%) ggc
expand : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 398 kB ( 2%) ggc
jump : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
loop init : 0.01 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 67 kB ( 0%) ggc
integrated RA : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 2468 kB (12%) ggc
thread pro- & epilogue : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 162 kB ( 1%) ggc
final : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 216 kB ( 1%) ggc
rest of compilation : 1.37 (69%) usr 0.00 ( 0%) sys 1.13 (18%) wall 1391 kB ( 6%) ggc
assemble JIT code : 0.01 ( 1%) usr 0.00 ( 0%) sys 4.04 (66%) wall 0 kB ( 0%) ggc
load JIT result : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
JIT client code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
Client items:
create_code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
compile : 0.36 (18%) usr 0.15 (83%) sys 0.86 (14%) wall 14939 kB (70%) ggc
running code : 0.00 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
TOTAL : 2.00 0.18 6.12 21444 kB
The exact format is intended to be human-readable, and is subject to change.
.. macro:: LIBGCCJIT_HAVE_TIMING_API
The timer API was added to libgccjit in GCC 6.
This macro is only defined in versions of libgccjit.h which have the
timer API, and so can be used to guard code that may need to compile
against earlier releases::
#ifdef LIBGCCJIT_HAVE_TIMING_API
gcc_jit_timer *t = gcc_jit_timer_new ();
gcc_jit_context_set_timer (ctxt, t);
#endif
.. type:: gcc_jit_timer
.. function:: gcc_jit_timer * gcc_jit_timer_new(void)
Create a :c:type:`gcc_jit_timer` instance, and start timing::
gcc_jit_timer *t = gcc_jit_timer_new ();
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API
.. function:: void gcc_jit_timer_release(gcc_jit_timer *timer)
Release a :c:type:`gcc_jit_timer` instance::
gcc_jit_timer_release (t);
This should be called exactly once on a timer.
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API
.. function:: void gcc_jit_context_set_timer(gcc_jit_context *ctxt, \
gcc_jit_timer *timer)
Associate a :c:type:`gcc_jit_timer` instance with a context::
gcc_jit_context_set_timer (ctxt, t);
A timer instance can be shared between multiple
:c:type:`gcc_jit_context` instances.
Timers have no locking, so if you have a multithreaded program, you
must provide your own locks if more than one thread could be working
with the same timer via timer-associated contexts.
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API
.. function:: gcc_jit_timer *gcc_jit_context_get_timer(gcc_jit_context *ctxt)
Get the timer associated with a context (if any).
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API
.. function:: void gcc_jit_timer_push(gcc_jit_timer *timer, \
const char *item_name)
Push the given item onto the timer's stack::
gcc_jit_timer_push (t, "running code");
run_the_code (ctxt, result);
gcc_jit_timer_pop (t, "running code");
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API
.. function:: void gcc_jit_timer_pop(gcc_jit_timer *timer, \
const char *item_name)
Pop the top item from the timer's stack.
If "item_name" is provided, it must match that of the top item.
Alternatively, ``NULL`` can be passed in, to suppress checking.
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API
.. function:: void gcc_jit_timer_print(gcc_jit_timer *timer, \
FILE *f_out)
Print timing information to the given stream about activity since
the timer was started.
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_TIMING_API

View File

@ -1793,7 +1793,7 @@ compile ()
}
/* This runs the compiler. */
toplev toplev (false, /* use_TV_TOTAL */
toplev toplev (get_timer (), /* external_timer */
false); /* init_signals */
enter_scope ("toplev::main");
if (get_logger ())
@ -2085,6 +2085,8 @@ static pthread_mutex_t jit_mutex = PTHREAD_MUTEX_INITIALIZER;
void
playback::context::acquire_mutex ()
{
auto_timevar tv (get_timer (), TV_JIT_ACQUIRING_MUTEX);
/* Acquire the big GCC mutex. */
JIT_LOG_SCOPE (get_logger ());
pthread_mutex_lock (&jit_mutex);
@ -2252,6 +2254,9 @@ make_fake_args (vec <char *> *argvec,
}
}
if (get_timer ())
ADD_ARG ("-ftime-report");
/* Add any user-provided extra options, starting with any from
parent contexts. */
m_recording_ctxt->append_command_line_options (argvec);
@ -2380,7 +2385,7 @@ invoke_driver (const char *ctxt_progname,
JIT_LOG_SCOPE (get_logger ());
/* Currently this lumps together both assembling and linking into
TV_ASSEMBLE. */
auto_timevar assemble_timevar (tv_id);
auto_timevar assemble_timevar (get_timer (), tv_id);
const char *errmsg;
auto_argvec argvec;
#define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
@ -2492,7 +2497,7 @@ playback::context::
dlopen_built_dso ()
{
JIT_LOG_SCOPE (get_logger ());
auto_timevar load_timevar (TV_LOAD);
auto_timevar load_timevar (get_timer (), TV_LOAD);
void *handle = NULL;
const char *error = NULL;
result *result_obj = NULL;

View File

@ -215,6 +215,8 @@ public:
return m_recording_ctxt->errors_occurred ();
}
timer *get_timer () const { return m_recording_ctxt->get_timer (); }
private:
void dump_generated_code ();

View File

@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "pretty-print.h"
#include "hash-map.h"
#include "toplev.h"
#include "timevar.h"
#include <pthread.h>
@ -461,6 +462,7 @@ recording::context::context (context *parent_ctxt)
: log_user (NULL),
m_parent_ctxt (parent_ctxt),
m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
m_timer (NULL),
m_error_count (0),
m_first_error_str (NULL),
m_owns_first_error_str (false),

View File

@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see
#include "jit-common.h"
#include "jit-logging.h"
class timer;
namespace gcc {
namespace jit {
@ -276,6 +278,9 @@ public:
void
get_all_requested_dumps (vec <recording::requested_dump> *out);
void set_timer (timer *t) { m_timer = t; }
timer *get_timer () const { return m_timer; }
private:
void log_all_options () const;
void log_str_option (enum gcc_jit_str_option opt) const;
@ -292,6 +297,8 @@ private:
contexts. This has itself as its own m_toplevel_ctxt. */
context *m_toplevel_ctxt;
timer *m_timer;
int m_error_count;
char *m_first_error_str;

View File

@ -46,6 +46,8 @@ namespace gccjit
class lvalue;
class param;
class case_;
class timer;
class auto_time;
/* Errors within the API become C++ exceptions of this class. */
class error
@ -125,6 +127,9 @@ namespace gccjit
void add_command_line_option (const char *optname);
void set_timer (gccjit::timer t);
gccjit::timer get_timer () const;
location
new_location (const std::string &filename,
int line,
@ -523,6 +528,36 @@ namespace gccjit
/* Dereferencing. */
lvalue operator* (rvalue ptr);
class timer
{
public:
timer ();
timer (gcc_jit_timer *inner_timer);
void push (const char *item_name);
void pop (const char *item_name);
void print (FILE *f_out) const;
void release ();
gcc_jit_timer *get_inner_timer () const;
private:
gcc_jit_timer *m_inner_timer;
};
class auto_time
{
public:
auto_time (timer t, const char *item_name);
auto_time (context ctxt, const char *item_name);
~auto_time ();
private:
timer m_timer;
const char *m_item_name;
};
}
/****************************************************************************
@ -636,6 +671,19 @@ context::add_command_line_option (const char *optname)
gcc_jit_context_add_command_line_option (m_inner_ctxt, optname);
}
inline void
context::set_timer (gccjit::timer t)
{
gcc_jit_context_set_timer (m_inner_ctxt, t.get_inner_timer ());
}
inline gccjit::timer
context::get_timer () const
{
return gccjit::timer (gcc_jit_context_get_timer (m_inner_ctxt));
}
inline location
context::new_location (const std::string &filename,
int line,
@ -1713,6 +1761,75 @@ inline lvalue operator* (rvalue ptr)
return ptr.dereference ();
}
// class timer
inline
timer::timer ()
{
m_inner_timer = gcc_jit_timer_new ();
}
inline
timer::timer (gcc_jit_timer *inner_timer)
{
m_inner_timer = inner_timer;
}
inline void
timer::push (const char *item_name)
{
gcc_jit_timer_push (m_inner_timer, item_name);
}
inline void
timer::pop (const char *item_name)
{
gcc_jit_timer_pop (m_inner_timer, item_name);
}
inline void
timer::print (FILE *f_out) const
{
gcc_jit_timer_print (m_inner_timer, f_out);
}
inline gcc_jit_timer *
timer::get_inner_timer () const
{
return m_inner_timer;
}
inline void
timer::release ()
{
gcc_jit_timer_release (m_inner_timer);
m_inner_timer = NULL;
}
// class auto_time
inline
auto_time::auto_time (timer t, const char *item_name)
: m_timer (t),
m_item_name (item_name)
{
t.push (item_name);
}
inline
auto_time::auto_time (context ctxt, const char *item_name)
: m_timer (ctxt.get_timer ()),
m_item_name (item_name)
{
m_timer.push (item_name);
}
inline
auto_time::~auto_time ()
{
m_timer.pop (m_item_name);
}
} // namespace gccjit
#endif /* #ifndef LIBGCCJIT_PLUS_PLUS_H */

View File

@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "safe-ctype.h"
#include "typed-splay-tree.h"
#include "timevar.h"
#include "libgccjit.h"
#include "jit-common.h"
@ -89,6 +90,10 @@ struct gcc_jit_case : public gcc::jit::recording::case_
{
};
struct gcc_jit_timer : public timer
{
};
/**********************************************************************
Error-handling.
@ -2828,3 +2833,107 @@ gcc_jit_result_release (gcc_jit_result *result)
result->log ("deleting result: %p", (void *)result);
delete result;
}
/**********************************************************************
Timing support.
**********************************************************************/
/* Create a gcc_jit_timer instance, and start timing. */
gcc_jit_timer *
gcc_jit_timer_new (void)
{
gcc_jit_timer *timer = new gcc_jit_timer ();
timer->start (TV_TOTAL);
timer->push (TV_JIT_CLIENT_CODE);
return timer;
}
/* Release a gcc_jit_timer instance. */
void
gcc_jit_timer_release (gcc_jit_timer *timer)
{
RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer");
delete timer;
}
/* Associate a gcc_jit_timer instance with a context. */
void
gcc_jit_context_set_timer (gcc_jit_context *ctxt,
gcc_jit_timer *timer)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt");
RETURN_IF_FAIL (timer, ctxt, NULL, "NULL timer");
ctxt->set_timer (timer);
}
/* Get the timer associated with a context (if any). */
gcc_jit_timer *
gcc_jit_context_get_timer (gcc_jit_context *ctxt)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt");
return (gcc_jit_timer *)ctxt->get_timer ();
}
/* Push the given item onto the timing stack. */
void
gcc_jit_timer_push (gcc_jit_timer *timer,
const char *item_name)
{
RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer");
RETURN_IF_FAIL (item_name, NULL, NULL, "NULL item_name");
timer->push_client_item (item_name);
}
/* Pop the top item from the timing stack. */
void
gcc_jit_timer_pop (gcc_jit_timer *timer,
const char *item_name)
{
RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer");
if (item_name)
{
const char *top_item_name = timer->get_topmost_item_name ();
RETURN_IF_FAIL_PRINTF1
(top_item_name, NULL, NULL,
"pop of empty timing stack (attempting to pop: \"%s\")",
item_name);
RETURN_IF_FAIL_PRINTF2
(0 == strcmp (item_name, top_item_name), NULL, NULL,
"mismatching item_name:"
" top of timing stack: \"%s\","
" attempting to pop: \"%s\"",
top_item_name,
item_name);
}
timer->pop_client_item ();
}
/* Print timing information to the given stream about activity since
the timer was started. */
void
gcc_jit_timer_print (gcc_jit_timer *timer,
FILE *f_out)
{
RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer");
RETURN_IF_FAIL (f_out, NULL, NULL, "NULL f_out");
timer->pop (TV_JIT_CLIENT_CODE);
timer->stop (TV_TOTAL);
timer->print (f_out);
timer->start (TV_TOTAL);
timer->push (TV_JIT_CLIENT_CODE);
}

View File

@ -1266,6 +1266,90 @@ gcc_jit_context_enable_dump (gcc_jit_context *ctxt,
const char *dumpname,
char **out_ptr);
/**********************************************************************
Timing support.
**********************************************************************/
/* The timing API was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
#define LIBGCCJIT_HAVE_TIMING_API
typedef struct gcc_jit_timer gcc_jit_timer;
/* Create a gcc_jit_timer instance, and start timing.
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern gcc_jit_timer *
gcc_jit_timer_new (void);
/* Release a gcc_jit_timer instance.
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern void
gcc_jit_timer_release (gcc_jit_timer *timer);
/* Associate a gcc_jit_timer instance with a context.
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern void
gcc_jit_context_set_timer (gcc_jit_context *ctxt,
gcc_jit_timer *timer);
/* Get the timer associated with a context (if any).
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern gcc_jit_timer *
gcc_jit_context_get_timer (gcc_jit_context *ctxt);
/* Push the given item onto the timing stack.
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern void
gcc_jit_timer_push (gcc_jit_timer *timer,
const char *item_name);
/* Pop the top item from the timing stack.
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern void
gcc_jit_timer_pop (gcc_jit_timer *timer,
const char *item_name);
/* Print timing information to the given stream about activity since
the timer was started.
This API entrypoint was added in LIBGCCJIT_ABI_4; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_TIMING_API
*/
extern void
gcc_jit_timer_print (gcc_jit_timer *timer,
FILE *f_out);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -128,3 +128,15 @@ LIBGCCJIT_ABI_3 {
gcc_jit_case_as_object;
gcc_jit_context_new_case;
} LIBGCCJIT_ABI_2;
# Add timing API.
LIBGCCJIT_ABI_4 {
global:
gcc_jit_context_get_timer;
gcc_jit_context_set_timer;
gcc_jit_timer_new;
gcc_jit_timer_release;
gcc_jit_timer_push;
gcc_jit_timer_pop;
gcc_jit_timer_print;
};

View File

@ -33,7 +33,7 @@ int main (int argc, char **argv);
int
main (int argc, char **argv)
{
toplev toplev (true, /* use_TV_TOTAL */
toplev toplev (NULL, /* external_timer */
true /* init_signals */);
return toplev.main (argc, argv);

View File

@ -1,3 +1,12 @@
2015-08-03 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-benchmark.c (test_jit): Add param "timer" and use
it to push/pop timing items.
(main): For each optimization level, create a gcc_jit_timer, and
time all of the iteration within that level cumulatively.
* jit.dg/test-error-gcc_jit_timer_pop-mismatch.c: New test case.
* jit.dg/test-error-gcc_jit_timer_pop-too-many.c: New test case.
2015-08-03 Alexander Basov <coohpt@gmail.com>
PR middle-end/64744

View File

@ -141,11 +141,13 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
/* Run one iteration of the test. */
static void
test_jit (const char *argv0, int opt_level)
test_jit (const char *argv0, int opt_level, gcc_jit_timer *timer)
{
gcc_jit_context *ctxt;
gcc_jit_result *result;
gcc_jit_timer_push (timer, "test_jit");
ctxt = gcc_jit_context_acquire ();
if (!ctxt)
{
@ -153,6 +155,8 @@ test_jit (const char *argv0, int opt_level)
return;
}
gcc_jit_context_set_timer (ctxt, timer);
/* Set up options. */
gcc_jit_context_set_str_option (
ctxt,
@ -182,13 +186,22 @@ test_jit (const char *argv0, int opt_level)
GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
1);
gcc_jit_timer_push (timer, "create_code");
create_code (ctxt, NULL);
gcc_jit_timer_pop (timer, "create_code");
gcc_jit_timer_push (timer, "compile");
result = gcc_jit_context_compile (ctxt);
gcc_jit_timer_pop (timer, "compile");
gcc_jit_timer_push (timer, "verify_code");
verify_code (ctxt, result);
gcc_jit_timer_pop (timer, "verify_code");
gcc_jit_context_release (ctxt);
gcc_jit_result_release (result);
gcc_jit_timer_pop (timer, "test_jit");
}
/* Taken from timevar.c. */
@ -217,16 +230,19 @@ main (int argc, char **argv)
int i;
double start_time, end_time, elapsed_time;
start_time = get_wallclock_time ();
gcc_jit_timer *timer = gcc_jit_timer_new ();
for (i = 1; i <= num_iterations; i++)
{
snprintf (test, sizeof (test),
"%s iteration %d of %d",
extract_progname (argv[0]),
i, num_iterations);
test_jit (argv[0], opt_level);
test_jit (argv[0], opt_level, timer);
}
end_time = get_wallclock_time ();
elapsed_time = end_time - start_time;
gcc_jit_timer_print (timer, stderr);
gcc_jit_timer_release (timer);
pass ("%s: survived %i iterations at optlevel %i",
argv[0], num_iterations, opt_level);
note (("%s: %i iterations at optlevel %i"

View File

@ -0,0 +1,22 @@
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit.h"
#include "harness.h"
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
gcc_jit_timer *timer = gcc_jit_timer_new ();
/* Error: mismatched push/pop. */
gcc_jit_timer_push (timer, "apples");
gcc_jit_timer_pop (timer, "oranges");
gcc_jit_timer_release (timer);
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
/* empty */
}

View File

@ -0,0 +1,21 @@
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit.h"
#include "harness.h"
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
gcc_jit_timer *timer = gcc_jit_timer_new ();
/* Erroneous: pop of an empty timing stack. */
gcc_jit_timer_pop (timer, "test");
gcc_jit_timer_release (timer);
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
/* empty */
}

View File

@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "timevar.h"
#ifndef HAVE_CLOCK_T
@ -120,6 +121,93 @@ static void timevar_accumulate (struct timevar_time_def *,
struct timevar_time_def *,
struct timevar_time_def *);
/* The implementation of timing events for jit client code, allowing
arbitrary named items to appear on the timing stack. */
class timer::named_items
{
public:
named_items (timer *t);
~named_items ();
void push (const char *item_name);
void pop ();
void print (FILE *fp, const timevar_time_def *total);
private:
/* Which timer instance does this relate to? */
timer *m_timer;
/* Dictionary, mapping from item names to timevar_def.
Note that currently we merely store/compare the raw string
pointers provided by client code; we don't take a copy,
or use strcmp. */
hash_map <const char *, timer::timevar_def> m_hash_map;
/* The order in which items were originally inserted. */
auto_vec <const char *> m_names;
};
/* The constructor for class timer::named_items. */
timer::named_items::named_items (timer *t)
: m_timer (t),
m_hash_map (),
m_names ()
{
}
/* The destructor for class timer::named_items. */
timer::named_items::~named_items ()
{
}
/* Push the named item onto the timer stack. */
void
timer::named_items::push (const char *item_name)
{
gcc_assert (item_name);
bool existed;
timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
if (!existed)
{
def->elapsed.user = 0;
def->elapsed.sys = 0;
def->elapsed.wall = 0;
def->name = item_name;
def->standalone = 0;
m_names.safe_push (item_name);
}
m_timer->push_internal (def);
}
/* Pop the top item from the timer stack. */
void
timer::named_items::pop ()
{
m_timer->pop_internal ();
}
/* Print the given client item. Helper function for timer::print. */
void
timer::named_items::print (FILE *fp, const timevar_time_def *total)
{
unsigned int i;
const char *item_name;
fprintf (fp, "Client items:\n");
FOR_EACH_VEC_ELT (m_names, i, item_name)
{
timer::timevar_def *def = m_hash_map.get (item_name);
gcc_assert (def);
m_timer->print_row (fp, total, 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. */
@ -169,7 +257,8 @@ timevar_accumulate (struct timevar_time_def *timer,
timer::timer () :
m_stack (NULL),
m_unused_stack_instances (NULL),
m_start_time ()
m_start_time (),
m_jit_client_items (NULL)
{
/* Zero all elapsed times. */
memset (m_timevars, 0, sizeof (m_timevars));
@ -190,6 +279,26 @@ timer::timer () :
#endif
}
/* Class timer's destructor. */
timer::~timer ()
{
timevar_stack_def *iter, *next;
for (iter = m_stack; iter; iter = next)
{
next = iter->next;
free (iter);
}
for (iter = m_unused_stack_instances; iter; iter = next)
{
next = iter->next;
free (iter);
}
delete m_jit_client_items;
}
/* Initialize timing variables. */
void
@ -212,9 +321,20 @@ void
timer::push (timevar_id_t timevar)
{
struct timevar_def *tv = &m_timevars[timevar];
push_internal (tv);
}
/* Push TV onto the timing stack, either one of the builtin ones
for a timevar_id_t, or one provided by client code to libgccjit. */
void
timer::push_internal (struct timevar_def *tv)
{
struct timevar_stack_def *context;
struct timevar_time_def now;
gcc_assert (tv);
/* Mark this timing variable as used. */
tv->used = 1;
@ -257,12 +377,21 @@ timer::push (timevar_id_t timevar)
void
timer::pop (timevar_id_t timevar)
{
gcc_assert (&m_timevars[timevar] == m_stack->timevar);
pop_internal ();
}
/* Pop the topmost item from the stack, either one of the builtin ones
for a timevar_id_t, or one provided by client code to libgccjit. */
void
timer::pop_internal ()
{
struct timevar_time_def now;
struct timevar_stack_def *popped = m_stack;
gcc_assert (&m_timevars[timevar] == m_stack->timevar);
/* What time is it? */
get_time (&now);
@ -410,6 +539,28 @@ timer::cond_stop (timevar_id_t timevar)
timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
}
/* Push the named item onto the timing stack. */
void
timer::push_client_item (const char *item_name)
{
gcc_assert (item_name);
/* Lazily create the named_items instance. */
if (!m_jit_client_items)
m_jit_client_items = new named_items (this);
m_jit_client_items->push (item_name);
}
/* Pop the top-most client item from the timing stack. */
void
timer::pop_client_item ()
{
gcc_assert (m_jit_client_items);
m_jit_client_items->pop ();
}
/* Validate that phase times are consistent. */
@ -462,6 +613,46 @@ timer::validate_phases (FILE *fp) const
}
}
/* Helper function for timer::print. */
void
timer::print_row (FILE *fp,
const timevar_time_def *total,
const timevar_def *tv)
{
/* The timing variable name. */
fprintf (fp, " %-24s:", 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 */
/* Print the amount of ggc memory allocated. */
fprintf (fp, "%8u kB (%2.0f%%) ggc",
(unsigned) (tv->elapsed.ggc_mem >> 10),
(total->ggc_mem == 0
? 0
: (float) tv->elapsed.ggc_mem / total->ggc_mem) * 100);
putc ('\n', fp);
}
/* Summarize timing variables to FP. The timing variable TV_TOTAL has
a special meaning -- it's considered to be the total elapsed time,
@ -494,6 +685,8 @@ timer::print (FILE *fp)
m_start_time = now;
fputs ("\nExecution times (seconds)\n", fp);
if (m_jit_client_items)
fputs ("GCC items:\n", fp);
for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
{
const timevar_def *tv = &m_timevars[(timevar_id_t) id];
@ -516,39 +709,10 @@ timer::print (FILE *fp)
&& tv->elapsed.ggc_mem < GGC_MEM_BOUND)
continue;
/* The timing variable name. */
fprintf (fp, " %-24s:", 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 */
/* Print the amount of ggc memory allocated. */
fprintf (fp, "%8u kB (%2.0f%%) ggc",
(unsigned) (tv->elapsed.ggc_mem >> 10),
(total->ggc_mem == 0
? 0
: (float) tv->elapsed.ggc_mem / total->ggc_mem) * 100);
putc ('\n', fp);
print_row (fp, total, tv);
}
if (m_jit_client_items)
m_jit_client_items->print (fp, total);
/* Print total time. */
fputs (" TOTAL :", fp);
@ -578,6 +742,17 @@ timer::print (FILE *fp)
validate_phases (fp);
}
/* Get the name of the topmost item. For use by jit for validating
inputs to gcc_jit_timer_pop. */
const char *
timer::get_topmost_item_name () const
{
if (m_stack)
return m_stack->timevar->name;
else
return NULL;
}
/* Prints a message to stderr stating that time elapsed in STR is
TOTAL (given in microseconds). */

View File

@ -296,3 +296,5 @@ DEFTIMEVAR (TV_JIT_REPLAY , "replay of JIT client activity")
DEFTIMEVAR (TV_ASSEMBLE , "assemble JIT code")
DEFTIMEVAR (TV_LINK , "link JIT code")
DEFTIMEVAR (TV_LOAD , "load JIT result")
DEFTIMEVAR (TV_JIT_ACQUIRING_MUTEX , "acquiring JIT mutex")
DEFTIMEVAR (TV_JIT_CLIENT_CODE , "JIT client code")

View File

@ -115,12 +115,24 @@ class timer
bool cond_start (timevar_id_t tv);
void cond_stop (timevar_id_t tv);
void push_client_item (const char *item_name);
void pop_client_item ();
void print (FILE *fp);
const char *get_topmost_item_name () const;
private:
/* Private member functions. */
void validate_phases (FILE *fp) const;
struct timevar_def;
void push_internal (struct timevar_def *tv);
void pop_internal ();
static void print_row (FILE *fp,
const timevar_time_def *total,
const timevar_def *tv);
private:
/* Private type: a timing variable. */
@ -157,6 +169,12 @@ class timer
struct timevar_stack_def *next;
};
/* A class for managing a collection of named timing items, for use
e.g. by libgccjit for timing client code. This class is declared
inside timevar.c to avoid everything using timevar.h
from needing vec and hash_map. */
class named_items;
private:
/* Data members (all private). */
@ -176,6 +194,11 @@ class timer
pushed. Time elapsed since then is attributed to the topmost
element. */
timevar_time_def m_start_time;
/* If non-NULL, for use when timing libgccjit's client code. */
named_items *m_jit_client_items;
friend class named_items;
};
/* Provided for backward compatibility. */
@ -198,15 +221,18 @@ timevar_pop (timevar_id_t tv)
class auto_timevar
{
public:
auto_timevar (timevar_id_t tv)
: m_tv (tv)
auto_timevar (timer *t, timevar_id_t tv)
: m_timer (t),
m_tv (tv)
{
timevar_push (m_tv);
if (m_timer)
m_timer->push (m_tv);
}
~auto_timevar ()
{
timevar_pop (m_tv);
if (m_timer)
m_timer->pop (m_tv);
}
private:
@ -214,6 +240,7 @@ class auto_timevar
// Private to disallow copies.
auto_timevar (const auto_timevar &);
timer *m_timer;
timevar_id_t m_tv;
};

View File

@ -1781,7 +1781,7 @@ static int rtl_initialized;
void
initialize_rtl (void)
{
auto_timevar tv (TV_INITIALIZE_RTL);
auto_timevar tv (g_timer, TV_INITIALIZE_RTL);
/* Initialization done just once per compilation, but delayed
till code generation. */
@ -2054,23 +2054,29 @@ do_compile ()
}
}
toplev::toplev (bool use_TV_TOTAL, bool init_signals)
: m_use_TV_TOTAL (use_TV_TOTAL),
toplev::toplev (timer *external_timer,
bool init_signals)
: m_use_TV_TOTAL (external_timer == NULL),
m_init_signals (init_signals)
{
if (!m_use_TV_TOTAL)
start_timevars ();
if (external_timer)
g_timer = external_timer;
}
toplev::~toplev ()
{
if (g_timer)
if (g_timer && m_use_TV_TOTAL)
{
g_timer->stop (TV_TOTAL);
g_timer->print (stderr);
delete g_timer;
g_timer = NULL;
}
}
/* Potentially call timevar_init (which will create g_timevars if it
doesn't already exist). */
void
toplev::start_timevars ()
{

View File

@ -24,11 +24,13 @@ along with GCC; see the file COPYING3. If not see
extern struct cl_decoded_option *save_decoded_options;
extern unsigned int save_decoded_options_count;
class timer;
/* Invoking the compiler. */
class toplev
{
public:
toplev (bool use_TV_TOTAL,
toplev (timer *external_timer,
bool init_signals);
~toplev ();