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:
parent
ef9da28d8f
commit
afed345982
@ -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
|
||||
|
@ -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"
|
||||
|
892
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
892
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
File diff suppressed because it is too large
Load Diff
@ -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`
|
||||
|
@ -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
|
||||
|
||||
|
@ -29,3 +29,4 @@ Topic Reference
|
||||
locations.rst
|
||||
compilation.rst
|
||||
compatibility.rst
|
||||
performance.rst
|
||||
|
240
gcc/jit/docs/topics/performance.rst
Normal file
240
gcc/jit/docs/topics/performance.rst
Normal 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
|
@ -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;
|
||||
|
@ -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 ();
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
22
gcc/testsuite/jit.dg/test-error-gcc_jit_timer_pop-mismatch.c
Normal file
22
gcc/testsuite/jit.dg/test-error-gcc_jit_timer_pop-mismatch.c
Normal 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 */
|
||||
}
|
21
gcc/testsuite/jit.dg/test-error-gcc_jit_timer_pop-too-many.c
Normal file
21
gcc/testsuite/jit.dg/test-error-gcc_jit_timer_pop-too-many.c
Normal 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 */
|
||||
}
|
245
gcc/timevar.c
245
gcc/timevar.c
@ -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). */
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
18
gcc/toplev.c
18
gcc/toplev.c
@ -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 ()
|
||||
{
|
||||
|
@ -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 ();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user