https://gcc.gnu.org/ml/jit/2013-q4/msg00023.html

GCC JIT vs others JIT ....

GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00023.html

From Paulo César Pereira de Andrade <paulo.cesar.pereira.de.andrade@gmail.com>

Hello David Malcom and all,

I am trying to understand what are the conceptual differences between
GCC JIT (when it will be mature enough) and other JIT libraries like GNU
lightning  or LLVM
 or GNU libjit  from
the point of view of the developer using the JIT library.

GNU lightning is probably much lower level than GCC JIT. It probably has
the advantage of generating quickly rather slow machine code. It mostly
gives a small set of register like variables.

LLVM probably is the equivalent competitor, since both GCC JIT and LLVM
are derived from ahead of time compilers (of course, for LLVM it was
initially not much true). So probably both GCC JIT and LLVM would
produce, a bit slowly, some good machine code. (In particular because
GCC JIT is, AFAIK, emitting assembly code).

BTW, I have no idea if GCC JIT has some option to set the optimization
level.

Libjit seems superficially similar in terms of API (to both LLVM and GCC
JIT): it offers a mini-C like intermediate representation.

I also believe that GCC JIT is probably the JIT library which runs on
much more processors than others (because GCC has a wide set of
targets).

David, do you think that a libit based JIT engine could quickly switch
to GCC JIT once it has matured? I am guessing it would be quite easy.

Cheers
-- 
Basile STARYNKEVITCH         
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***


Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00024.html

From Basile Starynkevitch <basile@starynkevitch.net>

On Tue, 2013-10-22 at 20:30 +0200, Basile Starynkevitch wrote:
> Hello David Malcom and all,

Hi Basile.

> I am trying to understand what are the conceptual differences between
> GCC JIT (when it will be mature enough) and other JIT libraries like GNU
> lightning  or LLVM
>  or GNU libjit  from
> the point of view of the developer using the JIT library.

I was aware of lightning and LLVM; I wasn't aware of libjit - thanks for
the link.

My interest is in modularising GCC's code, and I've been working for the
last few years on dynamic language runtimes (for Python), so turning GCC
into being usable for JIT use-cases is of great interest to me.

I tend to prefer fixing existing code over rewriting, hence my
preference for generalizing GCC to cover JIT workloads, over having a
separate JIT project: I'd prefer to have code shared between the
ahead-of-time compiler and the JIT compiler.  But other people may feel
differently, of course.

> GNU lightning is probably much lower level than GCC JIT. It probably has
> the advantage of generating quickly rather slow machine code. It mostly
> gives a small set of register like variables.

>From what I've seen of lightning it does indeed seem to have a much
lower level API compared to libgccjit.  It's probably faster: certainly
libgccjit isn't fast yet - for example, internally we're writing out
a .s file to disk, and then having to invoke other tools as subprocesses
to get that into a form we can execute.   I hope to eventually eliminate
that kludge (e.g. turn the GNU assembler into a library and use it
in-process, or perhaps even have GCC's RTL level directly emit machine
code instead of asm).  I deliberately hid the kludge behind the API, so
it should be possible to fix it without affecting ABI.

It's possible to see timing data by setting the bool option

   GCC_JIT_BOOL_OPTION_DUMP_SUMMARY

on the context; this is (very) roughly equivalent to running cc1 without
the -quiet option.

> LLVM probably is the equivalent competitor, since both GCC JIT and LLVM
> are derived from ahead of time compilers (of course, for LLVM it was
> initially not much true). So probably both GCC JIT and LLVM would
> produce, a bit slowly, some good machine code. (In particular because
> GCC JIT is, AFAIK, emitting assembly code).
(nods)   Yes, as described above, libgccjit does currently go through .s
files internally.
(my understanding of LLVM's origins are that it was for an ahead-of-time
compiler for doing a radical whole-program optimization that implements
pointer compression automatically)

> BTW, I have no idea if GCC JIT has some option to set the optimization
> level.

It does:

  gcc_jit_context_set_int_option (ctxt,        
                                  GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
                                  3);
is equivalent to "-O3" i.e. -O0 through -O3 are selectable.

0 is the default.   The API is simple for now.  I can add options for
enabling specific optimizations if people want, perhaps customization of
the pass pipeline (I implemented the pass_manager code in gcc 4.9 which
may help us to support such a use-case).

> Libjit seems superficially similar in terms of API (to both LLVM and GCC
> JIT): it offers a mini-C like intermediate representation.

Yes, looking at the API it looks similar to the API I came up with,
though I have rvalues vs lvalues, and there are no explicit blocks, only
label placement (you can always implement blocks by placing labels).

> I also believe that GCC JIT is probably the JIT library which runs on
> much more processors than others (because GCC has a wide set of
> targets).

I'd agree with that, though I'm speculating.  This is one of the reasons
for the very high-level nature of the API.

I'm conscious that I've only used the API to implement a method JIT, not
a tracing JIT; we may need additional constructs to help deal with the
kinds of dynamic code patching that a tracing JIT needs to do.

> David, do you think that a libit based JIT engine could quickly switch
> to GCC JIT once it has matured? I am guessing it would be quite easy.

I think so.

Out of interest, are you thinking of using this for MELT?  i.e.
embedding libgccjit inside a gcc plugin?  If so, I wonder if there could
be nasty interactions between the two copies of the GCC code?  libgccjit
has a symbol map that hides everything other than the 50 or so gcc_jit_*
entrypoints, so hopefully the two copies of the code would peacefully
coexist within the same address space - but it sounds like something to
be wary of.

Hope this is helpful
Dave

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00025.html

From David Malcolm <dmalcolm@redhat.com>

On Wed, 2013-10-23 at 00:24 -0400, David Malcolm wrote:
> Out of interest, are you thinking of using this for MELT?  i.e.
> embedding libgccjit inside a gcc plugin?  If so, I wonder if there could
> be nasty interactions between the two copies of the GCC code?  



(for other readers, MELT refers to  a high level
domain specific language to extend GCC; MELT is a GCC plugin -
generating C++ code fit into GCC)

Yes and no.

Indeed, I am thinking of LIBJIT or GCC JIT in something remotely related
to MELT, but that won't be in the MELT plugin.

I am dreaming of a MELT monitor, which would be an *external* process to
MELT and will :

    give a web interface to MELT, displaying code using Code Mirror
 

    communicate asynchronously with compilations using the MELT plugin

    store some persistent information


That MELT monitor could use JIT techniques (but it is a separate process
from cc1 or cc1plus -fplugin=melt ....). But there won't be nasty
interactions between the monitor and the cc1 because they are separate
processes - with some bi-directional pipes to communicate...

all this is just a dream today.
-- 
Basile STARYNKEVITCH         
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***


Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00027.html

From Basile Starynkevitch <basile@starynkevitch.net>

2013/10/22 Basile Starynkevitch <basile@starynkevitch.net>:
> Hello David Malcom and all,
>
> I am trying to understand what are the conceptual differences between
> GCC JIT (when it will be mature enough) and other JIT libraries like GNU
> lightning  or LLVM
>  or GNU libjit  from
> the point of view of the developer using the JIT library.
>
> GNU lightning is probably much lower level than GCC JIT. It probably has
> the advantage of generating quickly rather slow machine code. It mostly
> gives a small set of register like variables.

  GNU lightning does not use abstract "values", that may be either a
register or an immediate, it is required to explicitly state if the argument
is a register or an immediate, e.g. jit_addr(JIT_R0, JIT_R1, JIT_R2)
and jit_addi(JIT_R0, JIT_R1, 2). When using immediates, they are
always the last argument.

  GNU lightning major limitations are:
o Can call varargs but does not create varargs jit functions
o No dynamic alloca
o No aggregate arguments/return by value

  The major advantages are:
o Self contained, but binutils support is advised otherwise without
  disassembly, debugging may be quite difficult.
o Tailored for operations that need to know if there is overflow/carry
  and have the values ready (carry/borrow only need to know about,
  but multiplication high word and division remainder are quite useful).

  For starters, I would suggest looking at lightning's check/*.tst files,
for an overview of how to generate code. For example, bp.tst for
the classic recursive Fibonacci and fib.tst for the interactive one.
Other tests may be complex due to using the C preprocessor to
generate complex macros to brute force test all/most register/value
combinations.

  A more complex, still WIP, use case example of lightning is
 (lib/oemit*c files are the lightning
interfaces)

  Well, enough GNU lightning advertising :-)

> LLVM probably is the equivalent competitor, since both GCC JIT and LLVM
> are derived from ahead of time compilers (of course, for LLVM it was
> initially not much true). So probably both GCC JIT and LLVM would
> produce, a bit slowly, some good machine code. (In particular because
> GCC JIT is, AFAIK, emitting assembly code).
>
> BTW, I have no idea if GCC JIT has some option to set the optimization
> level.
>
> Libjit seems superficially similar in terms of API (to both LLVM and GCC
> JIT): it offers a mini-C like intermediate representation.
>
> I also believe that GCC JIT is probably the JIT library which runs on
> much more processors than others (because GCC has a wide set of
> targets).
>
> David, do you think that a libit based JIT engine could quickly switch
> to GCC JIT once it has matured? I am guessing it would be quite easy.
>
> Cheers
> --
> Basile STARYNKEVITCH         
> email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
> 8, rue de la Faiencerie, 92340 Bourg La Reine, France
> *** opinions {are only mine, sont seulement les miennes} ***


Paulo

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00032.html

From Paulo César Pereira de Andrade <paulo.cesar.pereira.de.andrade@gmail.com>

On Wed, 2013-10-23 at 13:22 -0200, Paulo CÃsar Pereira de Andrade wrote:
> 
>   A more complex, still WIP, use case example of lightning is
>  (lib/oemit*c files are the lightning
> interfaces)


Thanks for your message Paulo.

Actually, of all the JIT libraries I have cited, GNU lightning is
probabnly the one I am the more familiar with. Long time ago, I coded
ocamljit - a small JIT for ocaml bytecode - in it (but the current
ocamljit2 is probably unrelated to it).


I'm interested by your OWL work (did you know that as a computer
language, OWL means quite often
 ?)

But I am not able to find out some small examples of OWL code and/or
some syntax (and semantic) definition of your OWL. Or is OWL a JIT for
full C (e.g. able to interpret any C program)?

How do you code fibionacci and hello world in OWL? How do you code a
program reading a list of integers and computing the list of their
square?

And back to David Malcolm's GCC JIT, would you find easy to re-implement
OWL in it?

Cheers.

-- 
Basile STARYNKEVITCH         
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***


Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00033.html

From Basile Starynkevitch <basile@starynkevitch.net>

2013/10/23 Basile Starynkevitch <basile@starynkevitch.net>:
> On Wed, 2013-10-23 at 13:22 -0200, Paulo César Pereira de Andrade wrote:
>>
>>   A more complex, still WIP, use case example of lightning is
>>  (lib/oemit*c files are the lightning
>> interfaces)
>
>
> Thanks for your message Paulo.

  Hi Basile,

> Actually, of all the JIT libraries I have cited, GNU lightning is
> probabnly the one I am the more familiar with. Long time ago, I coded
> ocamljit - a small JIT for ocaml bytecode - in it (but the current
> ocamljit2 is probably unrelated to it).

  I did significant changes to lightning when I became maintainer of
it. Unless you used private interfaces (previously it was implemented
all in one pass as C macros, so, could not hide internals), basically
the main difference is that now function arguments are passed left
to right, and there is a large set of new ports.

> I'm interested by your OWL work (did you know that as a computer
> language, OWL means quite often
>  ?)

  I did not know about it.

> But I am not able to find out some small examples of OWL code and/or
> some syntax (and semantic) definition of your OWL. Or is OWL a JIT for
> full C (e.g. able to interpret any C program)?

  It is a C/C++ like language, with static and dynamic typing. The only
examples so far are in check/test, that you can cut&paste under gdb,
or just run "./owl check/test" to run all examples in a row. The file is quite
large, and growing, to help stress test the current implementation.

> How do you code fibionacci and hello world in OWL? How do you code a
> program reading a list of integers and computing the list of their
> square?

  It is still in the early stages of implementation, there are still too many
incomplete features, so, the best bet is to look in check/test that is
being used to slowly test code generation and correct code generation
bugs. But the hello world test is easy :-)

$ echo 'print("hello world!\n");' | ./owl
hello world!

  I promise to add working Fibonacci examples to check/test in my next
commit :-) There is an internal stream implementation, but only "exported"
so far is the print builtin, that prints to stdout, so the example of an integer
list would need to have the input encoded in a vector for now.

> And back to David Malcolm's GCC JIT, would you find easy to re-implement
> OWL in it?

  My interest is in  writing a managed language with dynamic typing,
and static typing for faster execution. But porting to gcc jit should not
be much different from the initial code I am writing, mainly to exercise
lightning, that would "optimize" when types are know, check for overflow
when it can happen and otherwise fallback to calling functions to
implement the vm primitives.

> Cheers.
>
> --
> Basile STARYNKEVITCH         
> email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
> 8, rue de la Faiencerie, 92340 Bourg La Reine, France
> *** opinions {are only mine, sont seulement les miennes} ***

Paulo

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00041.html

From Paulo César Pereira de Andrade <paulo.cesar.pereira.de.andrade@gmail.com>

On Wed, 2013-10-23 at 19:05 -0200, Paulo CÃsar Pereira de Andrade wrote:
[...]

>   It is a C/C++ like language, with static and dynamic typing. The only
> examples so far are in check/test, that you can cut&paste under gdb,
> or just run "./owl check/test" to run all examples in a row. The file is quite
> large, and growing, to help stress test the current implementation.

Is OWL compiling a function at a time (a "method JIT"), or are you
tracing execution paths and then optimizing hot loops (a "tracing JIT")?
(I've only attempted the former so far with my work)

[...]

>   My interest is in  writing a managed language with dynamic typing,
> and static typing for faster execution. But porting to gcc jit should not
> be much different from the initial code I am writing, mainly to exercise
> lightning, that would "optimize" when types are know, check for overflow
> when it can happen and otherwise fallback to calling functions to
> implement the vm primitives.

BTW, does lightning support self-modifying code?   (e.g. for doing
inline caching of attribute lookup).

Thanks
Dave

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00042.html

From David Malcolm <dmalcolm@redhat.com>

On Thu, 2013-10-24 at 14:53 -0400, David Malcolm wrote:
[...]
> BTW, does lightning support self-modifying code?   (e.g. for doing
> inline caching of attribute lookup).

But GCC does not (support self-modifying code). How would you make GCC
JIT accept it if GCC does not?

Cheers

-- 
Basile STARYNKEVITCH         
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***


Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00044.html

From Basile Starynkevitch <basile@starynkevitch.net>

On Thu, 2013-10-24 at 21:53 +0200, Basile Starynkevitch wrote:
> On Thu, 2013-10-24 at 14:53 -0400, David Malcolm wrote:
> [...]
> > BTW, does lightning support self-modifying code?   (e.g. for doing
> > inline caching of attribute lookup).
> 
> But GCC does not (support self-modifying code). How would you make GCC
> JIT accept it if GCC does not?

By making GCC handle it ;)

There may be things that are reasonable to do in a JIT that make little
sense for an AOT compiler, and self-modifying code is one of them, e.g.
for conditionals that almost always take one branch such as for
guard-style conditionals inside a loop, where we're recording the
assumptions about the types we're working on, with a 
   if (expr != expected_value)
and we don't expect the non-equal branch to ever be followed, but for
correctness it must exist, and we need to be able to update
expected_value.  In such a case, we want the most efficient check for
the commonly-executed case, and hardcoding expected_value inside the
compare instruction and then directly modifying it in place on the rare
chance it changes might be most efficient.

These are vague, long-term ideas, of course.

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00048.html

From David Malcolm <dmalcolm@redhat.com>

2013/10/24 David Malcolm <dmalcolm@redhat.com>:
> On Wed, 2013-10-23 at 19:05 -0200, Paulo César Pereira de Andrade wrote:
> [...]
>
>>   It is a C/C++ like language, with static and dynamic typing. The only
>> examples so far are in check/test, that you can cut&paste under gdb,
>> or just run "./owl check/test" to run all examples in a row. The file is quite
>> large, and growing, to help stress test the current implementation.
>
> Is OWL compiling a function at a time (a "method JIT"), or are you
> tracing execution paths and then optimizing hot loops (a "tracing JIT")?
> (I've only attempted the former so far with my work)

  For now it is more of a test environment for complex code generation
using lightning. It actually "compiles" a full owl script as a single C
callable function, uses its own stack, and does a precise mark&sweep
gc. Lightning itself can be used for either, as it only provides a kind of
portable, minimal assembly.

> [...]
>
>>   My interest is in  writing a managed language with dynamic typing,
>> and static typing for faster execution. But porting to gcc jit should not
>> be much different from the initial code I am writing, mainly to exercise
>> lightning, that would "optimize" when types are know, check for overflow
>> when it can happen and otherwise fallback to calling functions to
>> implement the vm primitives.
>
> BTW, does lightning support self-modifying code?   (e.g. for doing
> inline caching of attribute lookup).

  No. Lightning does mmap memory for the jit, attempting to waste as
few as possible memory, and after code generation it does mprotect
it removing write permission. Also does some voodoo for architectures
that need complex sequences to flush the code cache; currently
it requires gcc as the compiler, but libgcc __clear_cache does not
work on all ports.

> Thanks
> Dave

Paulo

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00049.html

From Paulo César Pereira de Andrade <paulo.cesar.pereira.de.andrade@gmail.com>

On Fri, 2013-10-25 at 13:15 -0200, Paulo CÃsar Pereira de Andrade wrote:
> 2013/10/24 David Malcolm <dmalcolm@redhat.com>:
> > On Wed, 2013-10-23 at 19:05 -0200, Paulo CÃsar Pereira de Andrade wrote:
> > [...]
> >
> >>   It is a C/C++ like language, with static and dynamic typing. The only
> >> examples so far are in check/test, that you can cut&paste under gdb,
> >> or just run "./owl check/test" to run all examples in a row. The file is quite
> >> large, and growing, to help stress test the current implementation.
> >
> > Is OWL compiling a function at a time (a "method JIT"), or are you
> > tracing execution paths and then optimizing hot loops (a "tracing JIT")?
> > (I've only attempted the former so far with my work)
> 
>   For now it is more of a test environment for complex code generation
> using lightning. It actually "compiles" a full owl script as a single C
> callable function, uses its own stack, and does a precise mark&sweep
> gc. Lightning itself can be used for either, as it only provides a kind of
> portable, minimal assembly.

Nice.

> > [...]
> >
> >>   My interest is in  writing a managed language with dynamic typing,
> >> and static typing for faster execution. But porting to gcc jit should not
> >> be much different from the initial code I am writing, mainly to exercise
> >> lightning, that would "optimize" when types are know, check for overflow
> >> when it can happen and otherwise fallback to calling functions to
> >> implement the vm primitives.
> >
> > BTW, does lightning support self-modifying code?   (e.g. for doing
> > inline caching of attribute lookup).
> 
>   No. Lightning does mmap memory for the jit, attempting to waste as
> few as possible memory, and after code generation it does mprotect
> it removing write permission. Also does some voodoo for architectures
> that need complex sequences to flush the code cache; currently
> it requires gcc as the compiler, but libgcc __clear_cache does not
> work on all ports.

Thanks.

FWIW one other approach I've seen is to mmap an anonymous fd twice, once
as writable, once as executable, giving the same underlying pages in two
different locations in the address space.   IIRC libffi uses this when
constructing wrappers to sidestep SELinux's restrictions on having pages
that are both writable and executable.   (I don't think that it has a
cache-flushing mechanism, since it has clearly separated phases of
"write,  then execute").

Re: GCC JIT vs others JIT ....

https://gcc.gnu.org/ml/jit/2013-q4/msg00040.html

From Paulo César Pereira de Andrade <paulo.cesar.pereira.de.andrade@gmail.com>

On Wed, 2013-10-23 at 13:22 -0200, Paulo CÃsar Pereira de Andrade wrote:

Hi Paulo

> 2013/10/22 Basile Starynkevitch <basile@starynkevitch.net>:
> > Hello David Malcom and all,
> >
> > I am trying to understand what are the conceptual differences between
> > GCC JIT (when it will be mature enough) and other JIT libraries like GNU
> > lightning  or LLVM
> >  or GNU libjit  from
> > the point of view of the developer using the JIT library.
> >
> > GNU lightning is probably much lower level than GCC JIT. It probably has
> > the advantage of generating quickly rather slow machine code. It mostly
> > gives a small set of register like variables.
> 
>   GNU lightning does not use abstract "values", that may be either a
> register or an immediate, it is required to explicitly state if the argument
> is a register or an immediate, e.g. jit_addr(JIT_R0, JIT_R1, JIT_R2)
> and jit_addi(JIT_R0, JIT_R1, 2). When using immediates, they are
> always the last argument.
> 
>   GNU lightning major limitations are:
> o Can call varargs but does not create varargs jit functions
> o No dynamic alloca
> o No aggregate arguments/return by value
> 
>   The major advantages are:
> o Self contained, but binutils support is advised otherwise without
>   disassembly, debugging may be quite difficult.
> o Tailored for operations that need to know if there is overflow/carry
>   and have the values ready (carry/borrow only need to know about,
>   but multiplication high word and division remainder are quite useful).

...and I'm fairly sure that your code has a *much* lower overhead than
mine (but improving GCC's startup time feels like an interesting
challenge).

>   For starters, I would suggest looking at lightning's check/*.tst files,
> for an overview of how to generate code. For example, bp.tst for
> the classic recursive Fibonacci and fib.tst for the interactive one.
> Other tests may be complex due to using the C preprocessor to
> generate complex macros to brute force test all/most register/value
> combinations.

Thanks.  Looks like the tests use an assembler-like syntax, which I'm
guessing gets parsed by a test harness.

>   A more complex, still WIP, use case example of lightning is
>  (lib/oemit*c files are the lightning
> interfaces)

Thanks for the link (and indeed for the work on the code)

>   Well, enough GNU lightning advertising :-)

:-)

Cheers
Dave