This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 15/16] gcc: Use libgas and libld within the driver


On Tue, Jun 2, 2015 at 1:06 PM, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> On Tue, Jun 02, 2015 at 10:31:53AM +0200, Richard Biener wrote:
>> On Mon, Jun 1, 2015 at 11:04 PM, David Malcolm <dmalcolm@redhat.com> wrote:
>> > This patch adds the ability for gcc to be configured with:
>> >   --with-embedded-as
>> >   --with-embedded-ld
>> > If so, invocations of "as" and "ld" are detected in the gcc driver, and
>> > specialcased by invoking these in-process as shared libraries.  This is
>> > intended for use by libgccjit, when the driver itself is in-process
>> > within libgccjit, eliminating fork/exec and dynamic-library resolution.
>> >
>> > Doing so dramatically speeds up jit.dg/test-benchmark.c.
>> >
>> > The patch generalizes the named items support within timevar.c, so that
>> > as well as having bucket of named "jit client items" we also have
>> > buckets for "as" and for "ld" so that they can account for time spent
>> > within them.
>> >
>> > One remaining hack here, appending CFLAGS-gcc.o with a hardcoded include
>> > path, but I didn't want that to hold up posting what I've got so far.
>>
>> Hum, so why not go further and embed as into cc1/cc1plus, etc.?  That is,
>> make the as invocation parts of the driver accessible to the compiler
>> in some way.
>
> It certainly seems like something worth looking into, but I certainly
> wouldn't want to hold binutils changes up on that.
>
>> This way we can eventually add a more efficient way of funneling the compiler
>> assembler output to libas (well, I suppose you at least use -pipe...).
>
> yeah, and eventually maybe dump a whole bunch of text formating code.  I
> wonder how much faster just doing this makes things though.

No idea.  Eventually just hooking up to libopcodes and feeding simple stmts
as binary blobs could work, keeping the textual interchange for the rest...

Richard.

> Trev
>
>>
>> Richard.
>>
>> > gcc/ChangeLog:
>> >         * configure.ac: Add --with-embedded-as and --with-embedded-ld.
>> >         * gcc.c: Include libgas.h and libld.h.
>> >         (class ctimershim): New.
>> >         (ctimershim::impl_push): New.
>> >         (ctimershim::impl_pop): New.
>> >         (run_embedded_as): New.
>> >         (run_embedded_ld): New.
>> >         (enum known_command): New.
>> >         (get_known_command): New.
>> >         (tv_id_for_known_command): New.
>> >         (maybe_run_embedded_command): New.
>> >         (execute): Invoke get_known_command and
>> >         maybe_run_embedded_command, potentially avoiding the need to call
>> >         into pex.
>> >         * timevar.c (timer::named_items::print): Add "name" param rather
>> >         than hardcoding "Client items".
>> >         (timer::timer): Initialize "m_has_named_items"; replace
>> >         "m_jit_client_items" with "m_named_items" array.
>> >         (timer::~timer): Likewise.
>> >         (timer::push_client_item): Rename to...
>> >         (timer::push_named_item): ...this and add "dict" param,
>> >         generalizing to support an array of dicts of named items.
>> >         (timer::pop_client_item): Rename to...
>> >         (timer::pop_named_item): ...this, generalizing to support
>> >         an array of dicts of named items.
>> >         (timer::print): Print JIT client items first (if any), then
>> >         GCC timevar items, then embedded as items (if any), then embedded
>> >         ld items (if any).
>> >         * timevar.def (TV_DRIVER_EMBEDDED_AS): New.
>> >         (TV_DRIVER_EMBEDDED_LD): New.
>> >         * timevar.h (timer::item_dict): New enum.
>> >         (timer::push_client_item): Rename to...
>> >         (timer::push_named_item): ...this, adding "dict" param.
>> >         (timer::pop_client_item): Rename to...
>> >         (timer::pop_named_item):  ...this, adding "dict" param.
>> >         (timer::get_item_dict): New.
>> >         (timer::m_jit_client_items): Drop this field in favor of...
>> >         (timer::m_named_items): ...this array.
>> >         (timer::m_has_named_items): New.
>> >
>> > gcc/jit/ChangeLog:
>> >         * Make-lang.in (LIBGCCJIT_FILENAME): Add EXTRA_GCC_LIBS to link.
>> >         * libgccjit.c (gcc_jit_timer_push): Replace call to
>> >         timer->push_client_item with timer->push_named_item.
>> >         (gcc_jit_timer_pop): Likewise for pop.
>> >         * notes.txt: Indicate that as/ld could be embedded.
>> > ---
>> >  gcc/Makefile.in      |   3 +
>> >  gcc/configure.ac     |  25 ++++++
>> >  gcc/gcc.c            | 214 ++++++++++++++++++++++++++++++++++++++++++++++++---
>> >  gcc/jit/Make-lang.in |   2 +-
>> >  gcc/jit/libgccjit.c  |   5 +-
>> >  gcc/jit/notes.txt    |   4 +-
>> >  gcc/timevar.c        |  56 ++++++++++----
>> >  gcc/timevar.def      |   2 +
>> >  gcc/timevar.h        |  33 +++++++-
>> >  9 files changed, 308 insertions(+), 36 deletions(-)
>> >
>> > diff --git a/gcc/Makefile.in b/gcc/Makefile.in
>> > index 2388975..9061933 100644
>> > --- a/gcc/Makefile.in
>> > +++ b/gcc/Makefile.in
>> > @@ -1993,6 +1993,9 @@ DRIVER_DEFINES = \
>> >
>> >  CFLAGS-gcc.o += $(DRIVER_DEFINES)
>> >
>> > +# FIXME
>> > +CFLAGS-gcc.o += -I/home/david/coding/gcc-python/binutils-gdb-libraries/install/include
>> > +
>> >  specs.h : s-specs ; @true
>> >  s-specs : Makefile
>> >         lsf="$(lang_specs_files)"; for f in $$lsf; do \
>> > diff --git a/gcc/configure.ac b/gcc/configure.ac
>> > index 810725c..6f50908 100644
>> > --- a/gcc/configure.ac
>> > +++ b/gcc/configure.ac
>> > @@ -1114,6 +1114,31 @@ LIBS=
>> >  AC_SEARCH_LIBS(kstat_open, kstat)
>> >  EXTRA_GCC_LIBS="$LIBS"
>> >  LIBS="$save_LIBS"
>> > +
>> > +# Support embedding libgas in the driver
>> > +
>> > +AC_ARG_WITH([embedded-as],
>> > + [AS_HELP_STRING([--with-embedded-as],
>> > +               [use libgas to embed the assembler in-process])],
>> > + [AC_CHECK_LIB([gas], [gas_main],
>> > +   [EXTRA_GCC_LIBS+=" -lgas $LDFLAGS";
>> > +    AC_DEFINE(HAVE_LIBGAS, 1,
>> > +       [Define if libgas is installed.])
>> > +   ],
>> > +   [AC_MSG_ERROR(["libgas not found"])])])
>> > +
>> > +# Support embedding libld in the driver
>> > +
>> > +AC_ARG_WITH([embedded-ld],
>> > + [AS_HELP_STRING([--with-embedded-ld],
>> > +                [use libld to embed the linker in-process])],
>> > + [AC_CHECK_LIB([ld], [ld_main],
>> > +               [EXTRA_GCC_LIBS+=" -lld $LDFLAGS";
>> > +                AC_DEFINE(HAVE_LIBLD, 1,
>> > +                [Define if libld is installed.])
>> > +               ],
>> > +               [AC_MSG_ERROR(["libld not found"])])])
>> > +
>> >  AC_SUBST(EXTRA_GCC_LIBS)
>> >
>> >  # Some systems put ldexp and frexp in libm instead of libc; assume
>> > diff --git a/gcc/gcc.c b/gcc/gcc.c
>> > index 93f41ec..ed92c7d 100644
>> > --- a/gcc/gcc.c
>> > +++ b/gcc/gcc.c
>> > @@ -45,6 +45,14 @@ compilation is specified by a string called a "spec".  */
>> >  #include "filenames.h"
>> >  #include "timevar.h"
>> >
>> > +#ifdef HAVE_LIBGAS
>> > +#include "libgas.h"
>> > +#endif
>> > +
>> > +#ifdef HAVE_LIBLD
>> > +#include "libld.h"
>> > +#endif
>> > +
>> >  /* Singleton instance of "driver" class.  */
>> >  static driver *g_driver;
>> >
>> > @@ -2807,6 +2815,190 @@ add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
>> >               require_machine_suffix, os_multilib);
>> >  }
>> >
>> > +
>> > +/* An implementation of the ctimer hooks C API, forwarding to
>> > +   our C++ "timer" class, for a particular timer::item_dict.  */
>> > +class ctimershim : public ctimer
>> > +{
>> > + public:
>> > +  ctimershim (timer *t,
>> > +             enum timer::item_dict dict)
>> > +    : m_timer (t),
>> > +      m_dict (dict)
>> > +  {
>> > +    this->push = impl_push;
>> > +    this->pop = impl_pop;
>> > +  }
>> > +
>> > + private:
>> > +  static void impl_push (ctimer *that, const char *item_name);
>> > +  static void impl_pop (ctimer *that);
>> > +
>> > + private:
>> > +   timer *m_timer;
>> > +   enum timer::item_dict m_dict;
>> > +};
>> > +
>> > +/* Implement CTIMER_PUSH in terms of pushing a named item
>> > +   within the given item_dict.  */
>> > +void
>> > +ctimershim::impl_push (ctimer *that, const char *item_name)
>> > +{
>> > +  ctimershim *this_ = static_cast <ctimershim *> (that);
>> > +  gcc_assert (this_->m_timer);
>> > +  this_->m_timer->push_named_item (this_->m_dict, item_name);
>> > +}
>> > +
>> > +/* Implement CTIMER_POP in terms of popping the item
>> > +   from the given item_dict.  */
>> > +void
>> > +ctimershim::impl_pop (ctimer *that)
>> > +{
>> > +  ctimershim *this_ = static_cast <ctimershim *> (that);
>> > +  gcc_assert (this_->m_timer);
>> > +  this_->m_timer->pop_named_item (this_->m_dict);
>> > +}
>> > +
>> > +#ifdef HAVE_LIBGAS
>> > +
>> > +/* Invoke gas_main, passing in the driver's timer
>> > +   so that the gas code can record timing information into it.  */
>> > +
>> > +static int run_embedded_as (int argc, const char **argv)
>> > +{
>> > +  gcc_assert (g_driver);
>> > +  timer *driver_timer = g_driver->get_timer ();
>> > +  auto_timevar tv (driver_timer, TV_DRIVER_EMBEDDED_AS);
>> > +  if (0)
>> > +    {
>> > +      fprintf (stderr, "run_embedded_as: %i args\n", argc);
>> > +      for (int i = 0; i < argc; i++)
>> > +       fprintf (stderr, "  argv[%i]: %s\n", i, argv[i]);
>> > +    }
>> > +
>> > +  ctimershim ct (driver_timer, timer::ITEM_DICT_EMBEDDED_AS);
>> > +  return gas_main (argc,
>> > +                   argv,
>> > +                   0, /* "standalone" */
>> > +                  driver_timer ? &ct : NULL); /* "timer" */
>> > +}
>> > +
>> > +#endif /* #ifdef HAVE_LIBGAS */
>> > +
>> > +#ifdef HAVE_LIBLD
>> > +
>> > +/* Invoke ld_main, passing in the driver's timer
>> > +   so that the linker code can record timing information into it.  */
>> > +
>> > +static int run_embedded_ld (int argc, const char **argv)
>> > +{
>> > +  gcc_assert (g_driver);
>> > +  timer *driver_timer = g_driver->get_timer ();
>> > +  auto_timevar tv (driver_timer, TV_DRIVER_EMBEDDED_LD);
>> > +  if (0)
>> > +    {
>> > +      fprintf (stderr, "run_embedded_ld: %i args\n", argc);
>> > +      for (int i = 0; i < argc; i++)
>> > +       fprintf (stderr, "  argv[%i]: %s\n", i, argv[i]);
>> > +    }
>> > +
>> > +  ctimershim ct (driver_timer, timer::ITEM_DICT_EMBEDDED_LD);
>> > +  return ld_main (argc,
>> > +                  argv,
>> > +                  0, /* "standalone" */
>> > +                  driver_timer ? &ct : NULL); /* struct ctimer *  */
>> > +}
>> > +
>> > +#endif /* #ifdef HAVE_LIBLD */
>> > +
>> > +/* The result of get_known_command.  */
>> > +
>> > +enum known_command
>> > +{
>> > +  KNOWN_COMMAND_AS,
>> > +  KNOWN_COMMAND_COLLECT2,
>> > +  KNOWN_COMMAND_LD,
>> > +  KNOWN_COMMAND_OTHER, /* not a known command, or a pipeline.  */
>> > +  NUM_KNOWN_COMMANDS
>> > +};
>> > +
>> > +/* Do we have an invocation of a single, known command, with no pipes?
>> > +   We can use this for selecting a timevar_id_t for the pex invocation,
>> > +   and potentially for running the command in-process.  */
>> > +
>> > +static enum known_command
>> > +get_known_command (int n_commands, const char *argv0)
>> > +{
>> > +  if (n_commands == 1)
>> > +    {
>> > +      if (0 == strcmp (argv0, "as"))
>> > +       return KNOWN_COMMAND_AS;
>> > +      else if (0 == strcmp (argv0, "collect2"))
>> > +       return KNOWN_COMMAND_COLLECT2;
>> > +      else if (0 == strcmp (argv0, "ld"))
>> > +       return KNOWN_COMMAND_LD;
>> > +    }
>> > +  return KNOWN_COMMAND_OTHER;
>> > +}
>> > +
>> > +/* If we're timing things, and we have a single command in the
>> > +   pipeline, bill the time to that command.  Given that we
>> > +   need a timevar for each one, we only split out a few important
>> > +   commands. */
>> > +
>> > +const timevar_id_t tv_id_for_known_command[NUM_KNOWN_COMMANDS] = {
>> > +  TV_DRIVER_EXECUTE_AS,
>> > +  TV_DRIVER_EXECUTE_COLLECT2,
>> > +  TV_DRIVER_EXECUTE_LD,
>> > +  TV_DRIVER_EXECUTE_OTHER
>> > +};
>> > +
>> > +/* Optimization: if we have a single, known command, and we're linked
>> > +   against an embedded copy of it, call it directly in-process, avoiding
>> > +   the overhead of fork/exec/dynamic link.
>> > +
>> > +   Return true if an embedded command was run, writing the result to
>> > +   *RESULT_OUT.
>> > +   Return false if no embedded command was available, leading *result_out
>> > +   untouched.  */
>> > +
>> > +static bool
>> > +maybe_run_embedded_command (enum known_command known_command,
>> > +                           int *result_out ATTRIBUTE_UNUSED)
>> > +{
>> > +#if defined (HAVE_LIBGAS) || defined (HAVE_LIBLD)
>> > +  int argc = argbuf.length ();
>> > +  const char **argv = argbuf.address ();
>> > +#endif
>> > +
>> > +  switch (known_command)
>> > +    {
>> > +    case KNOWN_COMMAND_AS:
>> > +#ifdef HAVE_LIBGAS
>> > +      *result_out = run_embedded_as (argc, argv);
>> > +      return true;
>> > +#else
>> > +      return false;
>> > +#endif
>> > +
>> > +    case KNOWN_COMMAND_COLLECT2:
>> > +      return false;
>> > +
>> > +    case KNOWN_COMMAND_LD:
>> > +#ifdef HAVE_LIBLD
>> > +      *result_out = run_embedded_ld (argc, argv);
>> > +      return true;
>> > +#else
>> > +      return false;
>> > +#endif
>> > +
>> > +    default:
>> > +      gcc_unreachable ();
>> > +    case KNOWN_COMMAND_OTHER:
>> > +      return false;
>> > +    }
>> > +}
>> > +
>> >  /* Execute the command specified by the arguments on the current line of spec.
>> >     When using pipes, this includes several piped-together commands
>> >     with `|' between them.
>> > @@ -2845,23 +3037,23 @@ execute (void)
>> >      if (strcmp (arg, "|") == 0)
>> >        n_commands++;
>> >
>> > +  /* Determine if we're dealing with a single embeddable command.  */
>> > +  enum known_command known_command = get_known_command (n_commands,
>> > +                                                       argbuf[0]);
>> > +
>> > +  /* Optimization: potentially avoid fork/exec by calling the command
>> > +     as a function in-process.  */
>> > +  int result;
>> > +  if (maybe_run_embedded_command (known_command, &result))
>> > +    return result;
>> > +
>> >    /* If we're timing things, and we have a single command in the
>> >       pipeline, bill the time to that command.  Given that we
>> >       need a timevar for each one, we only split out a few important
>> >       commands. */
>> > -  timevar_id_t tv_id;
>> > -  tv_id = TV_DRIVER_EXECUTE_OTHER;
>> >    gcc_assert (g_driver);
>> >    timer *driver_timer = g_driver->get_timer ();
>> > -  if (driver_timer && n_commands == 1)
>> > -    {
>> > -      if (0 == strcmp (argbuf[0], "as"))
>> > -       tv_id = TV_DRIVER_EXECUTE_AS;
>> > -      else if (0 == strcmp (argbuf[0], "collect2"))
>> > -       tv_id = TV_DRIVER_EXECUTE_COLLECT2;
>> > -      else if (0 == strcmp (argbuf[0], "ld"))
>> > -       tv_id = TV_DRIVER_EXECUTE_LD;
>> > -    }
>> > +  timevar_id_t tv_id = tv_id_for_known_command[known_command];
>> >    auto_timevar tv (driver_timer, tv_id);
>> >
>> >    /* Get storage for each command.  */
>> > diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
>> > index 9cff752..a7efe2e 100644
>> > --- a/gcc/jit/Make-lang.in
>> > +++ b/gcc/jit/Make-lang.in
>> > @@ -84,7 +84,7 @@ $(LIBGCCJIT_FILENAME): $(jit_OBJS) \
>> >         +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ -shared \
>> >              $(jit_OBJS) libbackend.a libcommon-target.a libcommon.a \
>> >              $(CPPLIB) $(LIBDECNUMBER) $(LIBS) $(BACKENDLIBS) \
>> > -            $(EXTRA_GCC_OBJS) \
>> > +            $(EXTRA_GCC_OBJS) $(EXTRA_GCC_LIBS) \
>> >              -Wl,--version-script=$(srcdir)/jit/libgccjit.map \
>> >              -Wl,-soname,$(LIBGCCJIT_SONAME)
>> >
>> > diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
>> > index 2a67ef7..8eee2da 100644
>> > --- a/gcc/jit/libgccjit.c
>> > +++ b/gcc/jit/libgccjit.c
>> > @@ -2431,7 +2431,8 @@ gcc_jit_timer_push (gcc_jit_timer *timer,
>> >  {
>> >    RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer");
>> >    RETURN_IF_FAIL (item_name, NULL, NULL, "NULL item_name");
>> > -  timer->push_client_item (item_name);
>> > +  timer->push_named_item (timer::ITEM_DICT_JIT_CLIENT_CODE,
>> > +                         item_name);
>> >  }
>> >
>> >  /* Pop the top item from the timing stack.  */
>> > @@ -2441,7 +2442,7 @@ gcc_jit_timer_pop (gcc_jit_timer *timer)
>> >  {
>> >    RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer");
>> >    /* FIXME: mismatching item? */
>> > -  timer->pop_client_item ();
>> > +  timer->pop_named_item (timer::ITEM_DICT_JIT_CLIENT_CODE);
>> >  }
>> >
>> >  /* Print timing information to the given stream about activity since
>> > diff --git a/gcc/jit/notes.txt b/gcc/jit/notes.txt
>> > index 36e05cb..4469145 100644
>> > --- a/gcc/jit/notes.txt
>> > +++ b/gcc/jit/notes.txt
>> > @@ -81,8 +81,8 @@ Client Code   . Generated .            libgccjit.so
>> >                .           .      --> Convert assembler to DSO, via embedded
>> >                .           .          copy of driver:
>> >                .           .           driver::main ()
>> > -              .           .             invocation of "as"
>> > -              .           .             invocation of "ld"
>> > +              .           .             in-process libgas, or out-of-process invocation of "as"
>> > +              .           .             in-process libld, or out-of-process invocation of "ld"
>> >                .           .           driver::finalize ()
>> >                .           .      <----
>> >                .           .      â   .               .
>> > diff --git a/gcc/timevar.c b/gcc/timevar.c
>> > index 9bc62e6..28db5b4 100644
>> > --- a/gcc/timevar.c
>> > +++ b/gcc/timevar.c
>> > @@ -134,7 +134,7 @@ class timer::named_items
>> >
>> >    void push (const char *item_name);
>> >    void pop ();
>> > -  void print (FILE *fp, const timevar_time_def *total);
>> > +  void print (FILE *fp, const char *name, const timevar_time_def *total);
>> >
>> >   private:
>> >    /* Which timer instance does this relate to?  */
>> > @@ -197,11 +197,13 @@ timer::named_items::pop ()
>> >  /* Print the given client item.  Helper function for timer::print.  */
>> >
>> >  void
>> > -timer::named_items::print (FILE *fp, const timevar_time_def *total)
>> > +timer::named_items::print (FILE *fp,
>> > +                          const char *name,
>> > +                          const timevar_time_def *total)
>> >  {
>> >    unsigned int i;
>> >    const char *item_name;
>> > -  fprintf (fp, "Client items:\n");
>> > +  fprintf (fp, "%s:\n", name);
>> >    FOR_EACH_VEC_ELT (m_names, i, item_name)
>> >      {
>> >        timer::timevar_def *def = m_hash_map.get (item_name);
>> > @@ -260,11 +262,14 @@ timer::timer () :
>> >    m_stack (NULL),
>> >    m_unused_stack_instances (NULL),
>> >    m_start_time (),
>> > -  m_jit_client_items (NULL)
>> > +  m_has_named_items (false)
>> >  {
>> >    /* Zero all elapsed times.  */
>> >    memset (m_timevars, 0, sizeof (m_timevars));
>> >
>> > +  /* There are no named_timers yet.  */
>> > +  memset (m_named_items, 0, sizeof (m_named_items));
>> > +
>> >    /* Initialize the names of timing variables.  */
>> >  #define DEFTIMEVAR(identifier__, name__) \
>> >    m_timevars[identifier__].name = name__;
>> > @@ -298,7 +303,8 @@ timer::~timer ()
>> >        free (iter);
>> >      }
>> >
>> > -  delete m_jit_client_items;
>> > +  for (int i = 0; i < NUM_ITEM_DICTS; i++)
>> > +    delete m_named_items[i];
>> >  }
>> >
>> >  /* Initialize timing variables.  */
>> > @@ -544,24 +550,32 @@ timer::cond_stop (timevar_id_t timevar)
>> >  /* Push the named item onto the timing stack.  */
>> >
>> >  void
>> > -timer::push_client_item (const char *item_name)
>> > +timer::push_named_item (enum item_dict dict,
>> > +                       const char *item_name)
>> >  {
>> > +  gcc_assert (dict < NUM_ITEM_DICTS);
>> >    gcc_assert (item_name);
>> > -
>> >    /* Lazily create the named_items instance.  */
>> > -  if (!m_jit_client_items)
>> > -    m_jit_client_items = new named_items (this);
>> > +  named_items **item_dict = &m_named_items[dict];
>> > +  if (!*item_dict)
>> > +    *item_dict = new named_items (this);
>> > +  (*item_dict)->push (item_name);
>> >
>> > -  m_jit_client_items->push (item_name);
>> > +  m_has_named_items = true;
>> >  }
>> >
>> >  /* Pop the top-most client item from the timing stack.  */
>> >
>> >  void
>> > -timer::pop_client_item ()
>> > +timer::pop_named_item (enum item_dict dict)
>> >  {
>> > -  gcc_assert (m_jit_client_items);
>> > -  m_jit_client_items->pop ();
>> > +  gcc_assert (dict < NUM_ITEM_DICTS);
>> > +  named_items *item_dict = m_named_items[dict];
>> > +
>> > +  /* If this fails, we have a pop from something that was never pushed to.  */
>> > +  gcc_assert (item_dict);
>> > +
>> > +  item_dict->pop ();
>> >  }
>> >
>> >  /* Validate that phase times are consistent.  */
>> > @@ -687,7 +701,11 @@ timer::print (FILE *fp)
>> >    m_start_time = now;
>> >
>> >    fputs ("\nExecution times (seconds)\n", fp);
>> > -  if (m_jit_client_items)
>> > +  if (m_named_items[ITEM_DICT_JIT_CLIENT_CODE])
>> > +    m_named_items[ITEM_DICT_JIT_CLIENT_CODE]->print (fp,
>> > +                                                    "Client items",
>> > +                                                    total);
>> > +  if (m_has_named_items)
>> >      fputs ("GCC items:\n", fp);
>> >    for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
>> >      {
>> > @@ -713,8 +731,14 @@ timer::print (FILE *fp)
>> >
>> >        print_row (fp, total, tv);
>> >      }
>> > -  if (m_jit_client_items)
>> > -    m_jit_client_items->print (fp, total);
>> > +  if (m_named_items[ITEM_DICT_EMBEDDED_AS])
>> > +    m_named_items[ITEM_DICT_EMBEDDED_AS]->print (fp,
>> > +                                                "Embedded 'as'",
>> > +                                                total);
>> > +  if (m_named_items[ITEM_DICT_EMBEDDED_LD])
>> > +    m_named_items[ITEM_DICT_EMBEDDED_LD]->print (fp,
>> > +                                                "Embedded 'ld'",
>> > +                                                total);
>> >
>> >    /* Print total time.  */
>> >    fputs (" TOTAL                 :", fp);
>> > diff --git a/gcc/timevar.def b/gcc/timevar.def
>> > index ce9236d..2360b30 100644
>> > --- a/gcc/timevar.def
>> > +++ b/gcc/timevar.def
>> > @@ -292,8 +292,10 @@ DEFTIMEVAR (TV_DRIVER_SETUP          , "driver: setup")
>> >  DEFTIMEVAR (TV_DRIVER_SPEC          , "driver: do spec on infiles")
>> >  DEFTIMEVAR (TV_DRIVER_LINK          , "driver: run linker")
>> >  DEFTIMEVAR (TV_DRIVER_EXECUTE_AS     , "driver: executing \"as\"")
>> > +DEFTIMEVAR (TV_DRIVER_EMBEDDED_AS    , "driver: embedded assembler")
>> >  DEFTIMEVAR (TV_DRIVER_EXECUTE_COLLECT2, "driver: executing \"collect2\"")
>> >  DEFTIMEVAR (TV_DRIVER_EXECUTE_LD     , "driver: executing \"ld\"")
>> > +DEFTIMEVAR (TV_DRIVER_EMBEDDED_LD    , "driver: embedded linker")
>> >  DEFTIMEVAR (TV_DRIVER_EXECUTE_OTHER  , "driver: executing subprocess")
>> >  DEFTIMEVAR (TV_LINK                 , "link JIT code")
>> >  DEFTIMEVAR (TV_LOAD                 , "load JIT result")
>> > diff --git a/gcc/timevar.h b/gcc/timevar.h
>> > index d46dc88..a0133d2 100644
>> > --- a/gcc/timevar.h
>> > +++ b/gcc/timevar.h
>> > @@ -105,6 +105,16 @@ extern void timevar_cond_stop (timevar_id_t, bool);
>> >  class timer
>> >  {
>> >   public:
>> > +  /* Support for multiple collections of named timing items.  */
>> > +  enum item_dict
>> > +  {
>> > +    ITEM_DICT_JIT_CLIENT_CODE,
>> > +    ITEM_DICT_EMBEDDED_AS,
>> > +    ITEM_DICT_EMBEDDED_LD,
>> > +    NUM_ITEM_DICTS
>> > +  };
>> > +
>> > + public:
>> >    timer ();
>> >    ~timer ();
>> >
>> > @@ -115,12 +125,20 @@ 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 push_named_item (enum item_dict dict,
>> > +                       const char *item_name);
>> > +  void pop_named_item (enum item_dict dict);
>> >
>> >    void print (FILE *fp);
>> >
>> >   private:
>> > +  /* 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:
>> >    /* Private member functions.  */
>> >    void validate_phases (FILE *fp) const;
>> >
>> > @@ -131,6 +149,8 @@ class timer
>> >                          const timevar_time_def *total,
>> >                          const timevar_def *tv);
>> >
>> > +  named_items *get_item_dict (enum item_dict dict);
>> > +
>> >   private:
>> >
>> >    /* Private type: a timing variable.  */
>> > @@ -193,10 +213,15 @@ class timer
>> >       element.  */
>> >    timevar_time_def m_start_time;
>> >
>> > -  /* If non-NULL, for use when timing libgccjit's client code.  */
>> > -  named_items *m_jit_client_items;
>> > +  /* Array of named_items, which are created on demand, and hence
>> > +     may each be NULL/non-NULL.  */
>> > +  named_items *m_named_items[NUM_ITEM_DICTS];
>> >
>> >    friend class named_items;
>> > +
>> > +  /* Do we have any named items?  Affects the output of the "print"
>> > +     method.  */
>> > +  bool m_has_named_items;
>> >  };
>> >
>> >  /* Provided for backward compatibility.  */
>> > --
>> > 1.8.5.3
>> >


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]