On Sat, Oct 2, 2010 at 12:59 PM, nicolas geoffray < nicolas.geoffray at gmail.com> wrote:> Hi Talin, > > You are not doing something wrong, it is just that the LLVM optimizers > consider llvm.gcroot like a regular function call. The alloca is moved in > the first block most probably because the inliner anticipates another > optimization pass (the mem2reg). >OK, well, is there anything that can be done?> > Cheers, > Nicolas > > On Sat, Oct 2, 2010 at 8:28 PM, Talin <viridia at gmail.com> wrote: > >> I'm still putting the final touches on my stack crawler, and I've run into >> a problem having to do with function inlining and local stack roots. >> >> As you know, all local roots must be initialized before you can make any >> call to a function which might crawl the stack. My compiler ensures that all >> local variables of a function are allocated, declared as root, and >> initialized in the first block. >> >> However, the function inlining pass does not seem to preserve these >> constraints. For example, say I have a function F: >> >> void F() { >> f1(); >> f2(); >> } >> >> Let's say that f1() causes a stack crawl (perhaps by triggering a >> collection cycle), and that f2() declares a stack root 'a'. If the optimizer >> decides to inline f2, then by the time the GCPrinter is called the resulting >> code looks like this: >> >> - a = alloca >> - call f1 >> - call llvm.gcroot(a) >> - store null, a >> >> The inliner moved the alloca instruction to the top of the function, but >> not the call to llvm.gcroot or the initialization of the variable. In other >> words, the initialization of the root occurs *after* the call to f1. This >> means that the stack crawler is seeing garbage and therefore crashes hard. >> (Also, I've observed that the call to llvm.gcroot and the initialization >> might not even be in the first block anymore.) >> >> As per usual, I'm not sure if this is a bug in LLVM or my doing something >> wrong... >> >> -- >> -- Talin >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20101002/04d52b54/attachment.html>
nicolas geoffray
2010-Oct-02 21:44 UTC
[LLVMdev] Function inlining creates uninitialized stack roots
Sure. I think we can change the GC lowering pass to recognize all llvm.gcroot (not only the ones in the first block), and move them to the first block so that they are initialized by the pass later on. On Sat, Oct 2, 2010 at 10:58 PM, Talin <viridia at gmail.com> wrote:> On Sat, Oct 2, 2010 at 12:59 PM, nicolas geoffray < > nicolas.geoffray at gmail.com> wrote: > >> Hi Talin, >> >> You are not doing something wrong, it is just that the LLVM optimizers >> consider llvm.gcroot like a regular function call. The alloca is moved in >> the first block most probably because the inliner anticipates another >> optimization pass (the mem2reg). >> > > OK, well, is there anything that can be done? > >> >> Cheers, >> Nicolas >> >> On Sat, Oct 2, 2010 at 8:28 PM, Talin <viridia at gmail.com> wrote: >> >>> I'm still putting the final touches on my stack crawler, and I've run >>> into a problem having to do with function inlining and local stack roots. >>> >>> As you know, all local roots must be initialized before you can make any >>> call to a function which might crawl the stack. My compiler ensures that all >>> local variables of a function are allocated, declared as root, and >>> initialized in the first block. >>> >>> However, the function inlining pass does not seem to preserve these >>> constraints. For example, say I have a function F: >>> >>> void F() { >>> f1(); >>> f2(); >>> } >>> >>> Let's say that f1() causes a stack crawl (perhaps by triggering a >>> collection cycle), and that f2() declares a stack root 'a'. If the optimizer >>> decides to inline f2, then by the time the GCPrinter is called the resulting >>> code looks like this: >>> >>> - a = alloca >>> - call f1 >>> - call llvm.gcroot(a) >>> - store null, a >>> >>> The inliner moved the alloca instruction to the top of the function, but >>> not the call to llvm.gcroot or the initialization of the variable. In other >>> words, the initialization of the root occurs *after* the call to f1. This >>> means that the stack crawler is seeing garbage and therefore crashes hard. >>> (Also, I've observed that the call to llvm.gcroot and the initialization >>> might not even be in the first block anymore.) >>> >>> As per usual, I'm not sure if this is a bug in LLVM or my doing something >>> wrong... >>> >>> -- >>> -- Talin >>> >>> _______________________________________________ >>> LLVM Developers mailing list >>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>> >>> >> > > > -- > -- Talin >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20101002/7a0caa0b/attachment.html>
On Sat, Oct 2, 2010 at 2:44 PM, nicolas geoffray <nicolas.geoffray at gmail.com> wrote:> Sure. I think we can change the GC lowering pass to recognize all > llvm.gcroot (not only the ones in the first block), and move them to the > first block so that they are initialized by the pass later on. >That makes sense. Yes, that would help. There's also the issue of initializing the roots to NULL. I don't use the standard InitRoots facility that is inherited from GCStrategy (since it only works with pointer roots, and as you know I support more than that.) I had initially thought that it would be sufficient for me to initialize the roots to NULL in my compiler and simply set GCStrategy.InitRoots to false. However, I'm guessing that won't work, since there's no easy way for the GC lowering pass to tell which "store" instructions are root initializations which need to be moved to the top of the function. It looks like I am going to have to instead do custom lowering in my GCStrategy so that non-pointer roots get initialized to ConstantAggregateNull instead of ConstantPointerNull.> > > On Sat, Oct 2, 2010 at 10:58 PM, Talin <viridia at gmail.com> wrote: > >> On Sat, Oct 2, 2010 at 12:59 PM, nicolas geoffray < >> nicolas.geoffray at gmail.com> wrote: >> >>> Hi Talin, >>> >>> You are not doing something wrong, it is just that the LLVM optimizers >>> consider llvm.gcroot like a regular function call. The alloca is moved in >>> the first block most probably because the inliner anticipates another >>> optimization pass (the mem2reg). >>> >> >> OK, well, is there anything that can be done? >> >>> >>> Cheers, >>> Nicolas >>> >>> On Sat, Oct 2, 2010 at 8:28 PM, Talin <viridia at gmail.com> wrote: >>> >>>> I'm still putting the final touches on my stack crawler, and I've run >>>> into a problem having to do with function inlining and local stack roots. >>>> >>>> As you know, all local roots must be initialized before you can make any >>>> call to a function which might crawl the stack. My compiler ensures that all >>>> local variables of a function are allocated, declared as root, and >>>> initialized in the first block. >>>> >>>> However, the function inlining pass does not seem to preserve these >>>> constraints. For example, say I have a function F: >>>> >>>> void F() { >>>> f1(); >>>> f2(); >>>> } >>>> >>>> Let's say that f1() causes a stack crawl (perhaps by triggering a >>>> collection cycle), and that f2() declares a stack root 'a'. If the optimizer >>>> decides to inline f2, then by the time the GCPrinter is called the resulting >>>> code looks like this: >>>> >>>> - a = alloca >>>> - call f1 >>>> - call llvm.gcroot(a) >>>> - store null, a >>>> >>>> The inliner moved the alloca instruction to the top of the function, but >>>> not the call to llvm.gcroot or the initialization of the variable. In other >>>> words, the initialization of the root occurs *after* the call to f1. This >>>> means that the stack crawler is seeing garbage and therefore crashes hard. >>>> (Also, I've observed that the call to llvm.gcroot and the initialization >>>> might not even be in the first block anymore.) >>>> >>>> As per usual, I'm not sure if this is a bug in LLVM or my doing >>>> something wrong... >>>> >>>> -- >>>> -- Talin >>>> >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>> >>>> >>> >> >> >> -- >> -- Talin >> > >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20101002/a521e468/attachment.html>
Seemingly Similar Threads
- [LLVMdev] Function inlining creates uninitialized stack roots
- [LLVMdev] Function inlining creates uninitialized stack roots
- [LLVMdev] Function inlining creates uninitialized stack roots
- [LLVMdev] Patch to allow llvm.gcroot to work with non-pointer allocas.
- [LLVMdev] Patch to allow llvm.gcroot to work with non-pointer allocas.