MCJIT and Kaleidoscope Tutorial

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

MCJIT and Kaleidoscope Tutorial

Dmitri Rubinstein
Hi all,

I tried to modify Kaleidoscope Tutorial (toy.cpp from
llvm/examples/Kaleidoscope/Chapter7, LLVM 3.3 release branch) in order
to use MCJIT instead of JIT. I get segmentation fault when running
toy.cpp with fibonacci example from the tutorial. My modified toy.cpp is
in attachment and still works with JIT (when #define USE_MCJIT line is
commented out).

I read discussions regarding MCJIT in this mailing list, and I
understand it that MCJIT currently cannot be used in the same way as
JIT. The separate function-by-function (i.e. incremental) compilation
approach with getPointerToFunction, like the one used in the
Kaleidoscope tutorial, will not work. Is this correct or do I do
something wrong in my code ?

There was also a discussion about using multi-module approach instead of
getPointerToFunction, but it seems that support for this is not yet
available. I would like to know if there is any way currently to let
Kaleidoscope-style of compilation work with MCJIT, and if no when it
will be available ?

Also, even if MCJIT does not support currently this compilation style I
still not understand why getPointerToFunction returns me a non-NULL
pointer ? I expected to get at least assertion or a NULL pointer.

Thanks,

Dmitri

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

toy.cpp (34K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

Kaylor, Andrew
Hi Dmitri,

You might want to try replacing the call to JMM->invalidInstructionCache() with a call to TheExecutionEngine->finalizeObject().  If you are getting a non-NULL pointer from getPointerToFunction but it crashes when you try to call it, that is most likely because the memory for the generated code has not been marked as executable.  That happens inside finalizeObject, which also invalidates the code cache.

Even so, this will likely only work in cases where code generation is only invoked once.

You are correct that MCJIT won't work in this case because of the function-by-function approach used in the Kaleidoscope example.  Basically, with MCJIT once code has been generated for a module nothing else can be added to the Module.

Making Kaleidoscope work with MCJIT would require introducing some sort of scheme where a new module was created each time a new function was created.  In the current implementation of MCJIT in trunk it is at least theoretically possible to make such a solution work by also creating a new instance of the MCJIT engine for each Module.  It is our intention to enhance MCJIT to allow multiple modules to be handled by a single instance, but there would still be the requirement that once code was generated for a Module it couldn't be modified again.  There may also be some work necessary in the memory manager to link the modules together.

Obviously it wouldn't be a trivial job to modify the Kaleidoscope example to work with MCJIT, but I think it should be possible.

I don't have a concrete time frame for when multiple module support will be available in MCJIT.

-Andy

-----Original Message-----
From: Dmitri Rubinstein [mailto:[hidden email]]
Sent: Monday, June 03, 2013 4:57 AM
To: LLVM Dev
Cc: Kaylor, Andrew
Subject: MCJIT and Kaleidoscope Tutorial

Hi all,

I tried to modify Kaleidoscope Tutorial (toy.cpp from llvm/examples/Kaleidoscope/Chapter7, LLVM 3.3 release branch) in order to use MCJIT instead of JIT. I get segmentation fault when running toy.cpp with fibonacci example from the tutorial. My modified toy.cpp is in attachment and still works with JIT (when #define USE_MCJIT line is commented out).

I read discussions regarding MCJIT in this mailing list, and I understand it that MCJIT currently cannot be used in the same way as JIT. The separate function-by-function (i.e. incremental) compilation approach with getPointerToFunction, like the one used in the Kaleidoscope tutorial, will not work. Is this correct or do I do something wrong in my code ?

There was also a discussion about using multi-module approach instead of getPointerToFunction, but it seems that support for this is not yet available. I would like to know if there is any way currently to let Kaleidoscope-style of compilation work with MCJIT, and if no when it will be available ?

Also, even if MCJIT does not support currently this compilation style I still not understand why getPointerToFunction returns me a non-NULL pointer ? I expected to get at least assertion or a NULL pointer.

Thanks,

Dmitri

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

Dmitri Rubinstein
Hi Andrew,

Am 04.06.2013 02:13, schrieb Kaylor, Andrew:
> Hi Dmitri,
>
> You might want to try replacing the call to JMM->invalidInstructionCache() with a call to TheExecutionEngine->finalizeObject().  If you are getting a non-NULL pointer from getPointerToFunction but it crashes when you try to call it, that is most likely because the memory for the generated code has not been marked as executable.  That happens inside finalizeObject, which also invalidates the code cache.

Thanks a lot, this helped. Now I just see "Error: redefinition of
function" when I define new function, and this is expected.

I am curious about JMM->invalidInstructionCache(), which I found in
lli.cpp implementation. lli.cpp contains also call finalizeObject(), I
just overlooked it. lli.cpp calls finalizeObject(), which calls
applyPermissions, which in turn calls invalidateInstructionCache. So why
lli.cpp does call JMM->invalidInstructionCache() explicitely again ?

Also I think there is a bug in MCJIT::getPointerToFunction:

...
   StringRef BaseName = F->getName();
   if (BaseName[0] == '\1')
...

When BaseName is empty it triggers assertion. For example in
Kaleidoscope tutorial an unnamed function is created.

>
> Even so, this will likely only work in cases where code generation is only invoked once.
>
> You are correct that MCJIT won't work in this case because of the function-by-function approach used in the Kaleidoscope example.  Basically, with MCJIT once code has been generated for a module nothing else can be added to the Module.
>
> Making Kaleidoscope work with MCJIT would require introducing some sort of scheme where a new module was created each time a new function was created.  In the current implementation of MCJIT in trunk it is at least theoretically possible to make such a solution work by also creating a new instance of the MCJIT engine for each Module.  It is our intention to enhance MCJIT to allow multiple modules to be handled by a single instance, but there would still be the requirement that once code was generated for a Module it couldn't be modified again.  There may also be some work necessary in the memory manager to link the modules together.

When I correctly understand this multi-module incremental approach, I
would need to create a new module for any new function generated. Since
my new function will likely call another previously defined functions, I
will need to declare them in the new module too. Their implementations
already exist in the module(s) that I created in previous steps. And
memory manager will take care of linking object code generated from all
my incrementally created modules.

I am also using in my code ExecutionEngine::addGlobalMapping for
defining functions that are declared in LLVM code but defined in my
application. Will this work with MCJIT ?

>
> Obviously it wouldn't be a trivial job to modify the Kaleidoscope example to work with MCJIT, but I think it should be possible.
>
> I don't have a concrete time frame for when multiple module support will be available in MCJIT.

OK, I will try to make workarounds in my code as long as MCJIT does not
support multi-module fully.

Thanks,

Dmitri

>
> -Andy
>
> -----Original Message-----
> From: Dmitri Rubinstein [mailto:[hidden email]]
> Sent: Monday, June 03, 2013 4:57 AM
> To: LLVM Dev
> Cc: Kaylor, Andrew
> Subject: MCJIT and Kaleidoscope Tutorial
>
> Hi all,
>
> I tried to modify Kaleidoscope Tutorial (toy.cpp from llvm/examples/Kaleidoscope/Chapter7, LLVM 3.3 release branch) in order to use MCJIT instead of JIT. I get segmentation fault when running toy.cpp with fibonacci example from the tutorial. My modified toy.cpp is in attachment and still works with JIT (when #define USE_MCJIT line is commented out).
>
> I read discussions regarding MCJIT in this mailing list, and I understand it that MCJIT currently cannot be used in the same way as JIT. The separate function-by-function (i.e. incremental) compilation approach with getPointerToFunction, like the one used in the Kaleidoscope tutorial, will not work. Is this correct or do I do something wrong in my code ?
>
> There was also a discussion about using multi-module approach instead of getPointerToFunction, but it seems that support for this is not yet available. I would like to know if there is any way currently to let Kaleidoscope-style of compilation work with MCJIT, and if no when it will be available ?
>
> Also, even if MCJIT does not support currently this compilation style I still not understand why getPointerToFunction returns me a non-NULL pointer ? I expected to get at least assertion or a NULL pointer.
>
> Thanks,
>
> Dmitri
>

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

David Tweed
| I am curious about JMM->invalidInstructionCache(), which I found in
| lli.cpp implementation. lli.cpp contains also call finalizeObject(), I
| just overlooked it. lli.cpp calls finalizeObject(), which calls
| applyPermissions, which in turn calls invalidateInstructionCache. So why
| lli.cpp does call JMM->invalidInstructionCache() explicitely again ?

My suspicion is it's a historical development; because different
architectures do or don't actually require cache invalidation the calls have
tended not to be initially put in, then added when other architectures
started using the code. When I was doing some cosmetic changes related to
that I didn't touch lli because the impression seemed to be that it was very
little used these days, so erring on the safe side seemed more important
than being completely minimal. In general, nowadays lli is not an example of
the cleanest way to use MCJIT.

Cheers,
Dave




_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

Dmitri Rubinstein
In reply to this post by Dmitri Rubinstein

Am 04.06.2013 16:05, schrieb David Tweed:

> | I am curious about JMM->invalidInstructionCache(), which I found in
> | lli.cpp implementation. lli.cpp contains also call finalizeObject(), I
> | just overlooked it. lli.cpp calls finalizeObject(), which calls
> | applyPermissions, which in turn calls invalidateInstructionCache. So why
> | lli.cpp does call JMM->invalidInstructionCache() explicitely again ?
>
> My suspicion is it's a historical development; because different
> architectures do or don't actually require cache invalidation the calls have
> tended not to be initially put in, then added when other architectures
> started using the code. When I was doing some cosmetic changes related to
> that I didn't touch lli because the impression seemed to be that it was very
> little used these days, so erring on the safe side seemed more important
> than being completely minimal. In general, nowadays lli is not an example of
> the cleanest way to use MCJIT.

But then there is no clean example of using MCJIT at all, please correct
me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo,
and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are
not compatible with MCJIT, there is also no tutorial explaining how to
use MCJIT.

Best,
Dmitri

>
> Cheers,
> Dave
>
>
>

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

Malea, Daniel
The unit tests contain some example usage; check
unittests/ExecutionEngine/MCJIT. I don't believe there's an actual
tutorial on MCJIT...

Dan

On 2013-06-04 10:20 AM, "Dmitri Rubinstein"
<[hidden email]> wrote:

>
>Am 04.06.2013 16:05, schrieb David Tweed:
>> | I am curious about JMM->invalidInstructionCache(), which I found in
>> | lli.cpp implementation. lli.cpp contains also call finalizeObject(), I
>> | just overlooked it. lli.cpp calls finalizeObject(), which calls
>> | applyPermissions, which in turn calls invalidateInstructionCache. So
>>why
>> | lli.cpp does call JMM->invalidInstructionCache() explicitely again ?
>>
>> My suspicion is it's a historical development; because different
>> architectures do or don't actually require cache invalidation the calls
>>have
>> tended not to be initially put in, then added when other architectures
>> started using the code. When I was doing some cosmetic changes related
>>to
>> that I didn't touch lli because the impression seemed to be that it was
>>very
>> little used these days, so erring on the safe side seemed more important
>> than being completely minimal. In general, nowadays lli is not an
>>example of
>> the cleanest way to use MCJIT.
>
>But then there is no clean example of using MCJIT at all, please correct
>me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo,
>and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are
>not compatible with MCJIT, there is also no tutorial explaining how to
>use MCJIT.
>
>Best,
>Dmitri
>
>>
>> Cheers,
>> Dave
>>
>>
>>
>
>_______________________________________________
>LLVM Developers mailing list
>[hidden email]         http://llvm.cs.uiuc.edu
>http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

Kaylor, Andrew
In reply to this post by Dmitri Rubinstein
Hi Dmitri,

You're right.  The lli code should be cleaned up.  As David said, there was a time when the call to invalidate the instruction cache was necessary.  It isn't necessary anymore.

-Andy

-----Original Message-----
From: Dmitri Rubinstein [mailto:[hidden email]]
Sent: Tuesday, June 04, 2013 7:20 AM
To: David Tweed
Cc: Kaylor, Andrew; LLVM Dev
Subject: Re: [LLVMdev] MCJIT and Kaleidoscope Tutorial


Am 04.06.2013 16:05, schrieb David Tweed:

> | I am curious about JMM->invalidInstructionCache(), which I found in
> | lli.cpp implementation. lli.cpp contains also call finalizeObject(),
> | I just overlooked it. lli.cpp calls finalizeObject(), which calls
> | applyPermissions, which in turn calls invalidateInstructionCache. So
> | why lli.cpp does call JMM->invalidInstructionCache() explicitely again ?
>
> My suspicion is it's a historical development; because different
> architectures do or don't actually require cache invalidation the
> calls have tended not to be initially put in, then added when other
> architectures started using the code. When I was doing some cosmetic
> changes related to that I didn't touch lli because the impression
> seemed to be that it was very little used these days, so erring on the
> safe side seemed more important than being completely minimal. In
> general, nowadays lli is not an example of the cleanest way to use MCJIT.

But then there is no clean example of using MCJIT at all, please correct me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo, and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are not compatible with MCJIT, there is also no tutorial explaining how to use MCJIT.

Best,
Dmitri

>
> Cheers,
> Dave
>
>
>


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: MCJIT and Kaleidoscope Tutorial

Dmitri Rubinstein
Thank you for the hint. Now I am observing a different problem.

I am testing MCJIT with Kaleidoscope examples on x86_64 and ARM (since
JIT does not work on ARM). Kaleidoscope defines printd function in the
host code which is also available to the JIT. Then printd is used to
print double numbers 123.0 and 4.0. Instead of them 1.0 and 0.0 numbers
are output.

I further investigated this and created following example:

-- printd.c --
#include <stdio.h>

double printd(double X)
{
   printf("printd: %f\n", X);
   return 0;
}

-- print.c --
#include <stdio.h>

extern double printd(double X);

int main(int argc, char **argv)
{
   printd(123.0);
   printd(4.0);
   return 0;
}

I compile printd.c to shared library, which I then load with lli:

 > gcc printd.c -fPIC -shared -o printd.so
 > clang -Wall -c -emit-llvm -O3 print.c -o print.bc
 > lli -use-mcjit -load=./printd.so print.bc
printd: 1.000000
printd: 0.000000

When I put printd implementation into print.c everything works fine, I
get expected numbers. Also everything works fine when I use 'int
printi(int)' instead of 'double printd(double)'. Looks for me like a
linking/HardFP-ABI related problem. This problem does not appear on
x86_64 at all.

Any ideas ?

ARM configuration is QEMU with RaspberryPi Raspbian “wheezy” kernel,
hard float support. LLVM datalayout and triple produced by clang are:

target datalayout =
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
target triple = "armv4t-unknown-linux-gnueabihf"

Best,

Dmitri

Am 04.06.2013 18:10, schrieb Kaylor, Andrew:

> Hi Dmitri,
>
> You're right.  The lli code should be cleaned up.  As David said, there was a time when the call to invalidate the instruction cache was necessary.  It isn't necessary anymore.
>
> -Andy
>
> -----Original Message-----
> From: Dmitri Rubinstein [mailto:[hidden email]]
> Sent: Tuesday, June 04, 2013 7:20 AM
> To: David Tweed
> Cc: Kaylor, Andrew; LLVM Dev
> Subject: Re: [LLVMdev] MCJIT and Kaleidoscope Tutorial
>
>
> Am 04.06.2013 16:05, schrieb David Tweed:
>> | I am curious about JMM->invalidInstructionCache(), which I found in
>> | lli.cpp implementation. lli.cpp contains also call finalizeObject(),
>> | I just overlooked it. lli.cpp calls finalizeObject(), which calls
>> | applyPermissions, which in turn calls invalidateInstructionCache. So
>> | why lli.cpp does call JMM->invalidInstructionCache() explicitely again ?
>>
>> My suspicion is it's a historical development; because different
>> architectures do or don't actually require cache invalidation the
>> calls have tended not to be initially put in, then added when other
>> architectures started using the code. When I was doing some cosmetic
>> changes related to that I didn't touch lli because the impression
>> seemed to be that it was very little used these days, so erring on the
>> safe side seemed more important than being completely minimal. In
>> general, nowadays lli is not an example of the cleanest way to use MCJIT.
>
> But then there is no clean example of using MCJIT at all, please correct me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo, and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are not compatible with MCJIT, there is also no tutorial explaining how to use MCJIT.
>
> Best,
> Dmitri
>
>>
>> Cheers,
>> Dave
>>
>>
>>
>

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev