> In C, the ‘minimal’ part is called the ‘scope’. Variables are always destroyed in the inverse order to the order in which they are created and so it’s always trivial to translate each into a stack save followed by an alloca when the variable comes into scope and a stack restore when the variable goes out of scope. > >> 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? > > Exactly. Each alloca would allocate more memory. gcc used to have a bug that did this, which bit me in the past (about 15 years ago), where using a VLA in the form from my example would consume stack space in proportion to the sum of all values of i, rather than in proportion to the maximum value of i. > > DavidThe 'scope'in should be related to the block in IR - not? This would then be easy: just insert a stackSafe right infront of the alloca (as you suggested) and a restore at the end of the block... Alex
David Chisnall via llvm-dev
2017-Jul-25 15:46 UTC
[llvm-dev] why is llvm.stacksave() necessary?
On 25 Jul 2017, at 16:40, alex via llvm-dev <llvm-dev at lists.llvm.org> wrote:> >> In C, the ‘minimal’ part is called the ‘scope’. Variables are always destroyed in the inverse order to the order in which they are created and so it’s always trivial to translate each into a stack save followed by an alloca when the variable comes into scope and a stack restore when the variable goes out of scope. >> >>> 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? >> >> Exactly. Each alloca would allocate more memory. gcc used to have a bug that did this, which bit me in the past (about 15 years ago), where using a VLA in the form from my example would consume stack space in proportion to the sum of all values of i, rather than in proportion to the maximum value of i. >> >> David > > The 'scope'in should be related to the block in IR - not?No. LLVM IR has no notion of nested scopes (global and function are the only two scopes that exist), only of liveness. A value is considered live.> This would then be easy: just insert a stackSafe right infront of the > alloca (as you suggested) and a restore at the end of the block…Unless your source language permits flow control, in which case you must insert the stack restore in the block that unifies flow control at the end of the scope. Consider this example: void myfunc(void) { for (int i=0 ; i<4; i++) { double d[i]; if (i % 2) doSomethingWith(d); else doSomethingElseWith(d); } } The IR that clang generates for this is quite hard to read, but the key point is that the stack save and stack restore are in different basic blocks. David
> Unless your source language permits flow control, in which case you must insert the stack restore in the block that unifies flow control at the end of the scope. Consider this example: > > void myfunc(void) > { > for (int i=0 ; i<4; i++) > { > double d[i]; > if (i % 2) > doSomethingWith(d); > else > doSomethingElseWith(d); > } > } > > The IR that clang generates for this is quite hard to read, but the key point is that the stack save and stack restore are in different basic blocks. > > DavidAnother good example, thanks. I had a look at the ll and found that the restore is in the if.end block. I think it could also go into the for.inc block (just before jumping back to cond). Is there any way (from AST in C++) to easily identify 'the block that unifies flow control at the end of the scope'? does it have any special attribute one could search for? Alex