[LLVMdev] Work in progress patch to bug 2606

Garrison Venn gvenn.cfe.dev at gmail.com
Wed Feb 17 13:36:15 PST 2010


In thinking about this we could use a Mutex::tryacquire(...) (non-recursive), around JIT::runJITOnFunctionUnlocked(...)'s
while loop, and use your JITEmitter:: getLazyFunctionStub(...) suggestion in place of forceEmitFunctionStub(...). Is the lock
attempt too heavy, even if it is implemented with atomics? I'll implement this when I have time.

Garrison

On Feb 17, 2010, at 15:42, Garrison Venn wrote:

> Hi Olivier,
> 
> Thanks for responding! I get to learn this way.
> 
> On Feb 17, 2010, at 12:50, Olivier Meurant wrote:
> 
>> Hi Garrison,
>> 
>> I am not a specialist of the code but here is my 2 cents:
>> 
>> - I like the idea that in lazy-mode the call (in module or not) is treated by a stub (like every calls).
> 
> If we go further with this, I'll have to add test cases for lazy mode. I kind of ignored it thinking I'll wait to see what
> the group thinks about the approach.
> 
>> 
>> - If the jit is in non-lazy mode, I'm not really fan of the "stub" solution. Is it not possible to use the same mechanism as it already exists : add the function to pending list and emit it after the current functions ? In fact, can you replace forEmitFunctionStub with getLazyFunctionStub ? With a non-lazy jit, I want the first execution of my function to be the same execution speed as the second one. A stub in non-lazy mode doesn't fell natural to me.
> 
> So as best as I can determine, the problem with leveraging pending, as used by getLazyFunctionStub(...) is that 
> I don't know when to call JIT::updateFunctionStub(...). Ideally this behavior should be invoked in the outermost
> getPointerToFunctionCall(), but one doesn't know, as currently implemented, when this is. 
> 
> To be clearer, in order to prevent recursive function compilation cases, one needs to delay the compilation of a 
> function being called until after the current calling function is compiled. In other words to deal with the scenario 
> where Fa (module A), calls Fb (module B), which in turn calls Fa, we delay the compilation of Fb until we have 
> finished the compilation of  Fa, unless Fb has previously been compiled. Let's say we used JITEmitter::getLazyFunctionStub(...). 
> If a user called getPointerToFunction(...) on Fa, everything would work fine. In compiling Fa, getPointerToFunction(...)
> (via JIT::runJITOnFunctionUnlocked(...)) would encounter Fb in module B, run getLazyFunctionStub(...) on it, and 
> then finish with the evaluation of the pending list; again via runJITOnFunctionUnlocked(). The latter functionality
> would result in the compilation of Fb. Say however we instead had Fa1 call Fb, and Fa2 in sequence (Fa1, Fa2
> in module A, Fa2 not previously compiled). The former description would still hold up to the point Fa2 is encountered. 
> Since Fa2 is in Fa1's module, runJITOnFunctionUnlocked(...) would compile it, check the pending list, and update the 
> contained functions. Since the stub for Fb is in that pending list, Fb would be compiled at this time. However the compilation 
> of Fa1 is still not finished, and we have what I was trying to prevent. Any errors in my logic, or my understanding of the 
> code? MutexGuards are just mutexes, right? Seems one could use reader/writer lock semantics to force the handing of 
> the pending list only in the outmost runJITOnFunctionUnlocked(...) call. I should also add a test case for the above Fa1, 
> Fa2, Fb, use case in the bug's attachments.
> 
> Having said this I might be going down a rat hole. It would seem such recursive compilations dependencies would exist
> for functions in the same module, and these are handled. So I should probably look at that code. We are of course
> limited by the existing code, since this is a bug fix not a design change. 
> 
> You also have another point. It is dissatisfactory to have the first call delayed just because it is in another module.
> We could use another semantic where the pending list is handled outside of the outermost getPointerToFunction(...)
> is called. This is of course a design change.
> 
>> 
>> - I don't see why functions external to every modules (let's say "printf" ?) are delayed with your mechanism. In the last part of your modified getPointerToFunction, you call "getPointerToNamedFunction". AFAICT a printf call will be catch by this code, no ?
> 
> If I understand what your saying correctly: the printf will be caught here, but only after the module search is finished. In
> essence I was saying that with the bug fix, as compared to the pre-existing implementation, the handling of such
> external functions is delayed. If I could tell that the function belonged to this category before I did the module search
> then there would obviously be no delay. Is this possible? I have to say I'm being rather theoretical here. Delay, no delay;
> sounds like I'm trying to predict whether the tree fell in the forest. ;-) I just don't yet have the requisite LLVM knowledge to
> run empirical tests. I tend to hide behind worries of falling timber given the erudite nature of this list's membership. :-)
>  
>> 
>> - I like the ideas to be flexible, to be able to say this global variable declaration should point here (with addGlobalMapping), even if there is another module which have a global variable. And in fact, as the workaround is relatively easy, I wonder if it worth the change ?
> 
> I agree, I wonder if there should be a separate mode where a cross module find is turned on, with the default set to off. 
> In the optional new mode, stubs would be gathered and processed (until done), as a separate phase--a linking phase
> for JIT as exists in other LLVM JIT tools. I have not looked at those either.
> 
> 1) Should we close the bug by dismissing it as no longer appropriate?
> 2) Apply the approach as given, with possible changes, and fix the bug?
> 3) Create a new approach, still viewing the bug as valid?
> 4) Keep the bug open because the implied features are desired but require a minor design change to resolve?
> 5) Do other? 
> 
> Thanks again for looking at this Olivier.
> 
> Garrison
> 
>> 
>> Anyway, thanks for asking opinion on this and for contributions you've made on code !
>> 
>> Olivier.
>> 
>> 
>> On Tue, Feb 16, 2010 at 2:10 PM, Garrison Venn <gvenn.cfe.dev at gmail.com> wrote:
>> The patch I recently attached to bug 2606, reproduced here, is my first attempt to solve this issue
>> as represented by the attached test cases. To solve the foreign Module GlobalVariable problem,
>> I modified JIT::getOrEmitGlobalVariable(...) to directly attempt to map a found "external" GlobalVariable.
>> To solve the foreign Module Function problem, I modified both JIT.{h,cpp} and JITEmitter.cpp to emit
>> a stub for a found "external" Function instance, when that foreign Module defined Function has not
>> yet been compiled.
>> 
>> All areas of interest are marked with // GMV Mod:
>> 
>> As I've taken liberties with existing code, and thereby may have touched test cases that will fail, I would like
>> to have those members of the list that have time, review this proposal for comments/changes.
>> 
> 
> [snip]
> 
>> Thanks for any time spent on this
>> 
>> Garrison
>> 
>> 
>> 
>> 	
>> 
>> 
>> 
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>> 
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100217/5b3b361e/attachment.html>


More information about the llvm-dev mailing list