Hi all, the language reference for the alloca instruction states: The ‘alloca‘ instruction allocates memory on the stack frame of the currently executing function, to be automatically released when this function returns to its caller. when using come c code like void myfunc(void){ int i=4; double d[i]; } the ir shows enclosing llvm.stackSave & restore constructs, enclosing the alloca related to 'd'. thellvm.stacksafe reference explains: This intrinsic is used to remember the current state of the function stack... In practice, this pops any alloca blocks from the stack that were allocated after the llvm.stacksave was executed. shouldn't the alloca block related to 'd' be automatically released when the function returns to its caller? isn't the 'stack frame of the currently executing function'=='the function stack'? Can I programmatically decide when to insert calls to stacksafe/restore? Suppose I would have a pass which sometimes would introduce such dynamic alloca's - do I need to explicitely track this and insert stacksave/restore? Or could I check for dynamic alloca (one ore several) afterwards, and then introduce stacksave/restore once (enclosing the complete function code) after the completed pass? Thx Alex
David Chisnall via llvm-dev
2017-Jul-25 09:13 UTC
[llvm-dev] why is llvm.stacksave() necessary?
> On 25 Jul 2017, at 10:04, alex via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > Hi all, > > the language reference for the alloca instruction states: > The ‘alloca‘ instruction allocates memory on the stack frame of the > currently executing function, to be automatically released when this > function returns to its caller. > > when using come c code like > void myfunc(void){ > int i=4; > double d[i]; > } > > the ir shows enclosing llvm.stackSave & restore constructs, enclosing > the alloca related to 'd’.Clang does this because clang intentionally generates IR naïvely and relies on LLVM optimisation passes to clean it up. In the case of C VLAs, the size of the alloca changes whenever the declaration goes into scope. By emitting a stack save and restore for d, clang doesn’t need to have different IR generating code for your example and for this one: void myfunc(void { for (int i=0 ; i<4; i++) { double d[i]; doSomethingWith(d); } } In this case, each time that the loop is entered you will get a new d with a different size. Clang emits code that handles this case, and an early optimisation pass will remove the stack save and stack restore intrinsics if they’re not actually needed. David
> Clang does this because clang intentionally generates IR naïvely and relies on LLVM optimisation passes to clean it up. > > In the case of C VLAs, the size of the alloca changes whenever the declaration goes into scope. By emitting a stack save and restore for d, clang doesn’t need to have different IR generating code for your example and for this one: > > void myfunc(void > { > for (int i=0 ; i<4; i++) > { > double d[i]; > doSomethingWith(d); > } > } > > In this case, each time that the loop is entered you will get a new d with a different size. Clang emits code that handles this case, and an early optimisation pass will remove the stack save and stack restore intrinsics if they’re not actually needed. > > DavidHi David, good example, thank you. This means than, when generating VLA's, one would need to check for the 'minimal' part which needs to be enclosed by safe/remove (in this example the related calls need to enclose the inner part of the loop). what would happen if stack safe/remove would be neglected? at the end of the function everything should get cleaned-up - right?; the only problem could be that one consumes much more stack than necessary - not? Thx Alex