David Chisnall
2015-Apr-05 09:44 UTC
[LLVMdev] alloca not in first bb behaving differently
It's not great IR, but it doesn't look like it should actually crash, just (without SROA) produce comparatively bad code. The alloca is only referenced in the basic block that it exists. If this isn't expected to work, then we should probably improve the documentation of alloca in the language reference. David> On 5 Apr 2015, at 04:55, Eric Christopher <echristo at gmail.com> wrote: > > Allocas not in the entry block are treated as dynamic allocas and not stack slots. > > > On Sat, Apr 4, 2015, 8:37 PM Dave Pitsbawn <dpitsbawn at gmail.com> wrote: > Here is some IR that is working and executing as expected -- All allocas are in the first basic block, and only updates happen in other basic blocks. > > define i32 @f() { > entry: > %x = alloca i32 > store i32 333, i32* %x > %i = alloca i32 > store i32 11, i32* %i > br i1 true, label %if.then, label %if.else > > if.then: ; preds = %entry > store i32 3, i32* %i > %0 = load i32* %i > ret i32 %0 > > if.else: ; preds = %entry > ret i32 2 > > if.end: ; preds = %after_ret1, %after_ > ret > ret i32 1 > > after_ret: ; No predecessors! > br label %if.end > > after_ret1: ; No predecessors! > br label %if.end > > after_ret2: ; No predecessors! > ret i32 0 > } > > The following IR is slightly different in that the alloca is defined not in the first basic block: > > define i32 @M() { > entry: > %x = alloca i32 > store i32 333, i32* %x > br i1 true, label %if.then, label %if.else > > if.then: ; preds = %entry > %i = alloca i32 > store i32 3, i32* %i > %0 = load i32* %i > ret i32 %0 > > if.else: ; preds = %entry > ret i32 2 > > if.end: ; preds = %after_ret1, %after_ > ret > ret i32 1 > > after_ret: ; No predecessors! > br label %if.end > > after_ret1: ; No predecessors! > br label %if.end > > after_ret2: ; No predecessors! > ret i32 0 > } > > This segfaults for me. The IR passes the function verifier. Can someone spot an error? I don't see any. > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Data point: I use (rarely) alloca in basic blocks other than the entry block, and it works. The one point to be aware of: alloca is "cleaned up" only when the function returns. If you use alloca in a loop, and you have no other mechanism to deal with it, you will blow out your stack and segfault. One way to deal with this is to use llvm.stacksave before the alloca ad llvm.stackrestore after you're done. These functions can serve to do "proper" middle-block allocations, creating temporary storage that is valid only as long as you need it. Note to self: good call to do all of your "longer term" allocas in the entry block. Don't move them to inner blocks even if you think you can, as SROA won't touch them. On Sun, Apr 5, 2015 at 5:44 AM, David Chisnall <David.Chisnall at cl.cam.ac.uk> wrote:> It's not great IR, but it doesn't look like it should actually crash, just > (without SROA) produce comparatively bad code. The alloca is only > referenced in the basic block that it exists. If this isn't expected to > work, then we should probably improve the documentation of alloca in the > language reference. > > David > > > On 5 Apr 2015, at 04:55, Eric Christopher <echristo at gmail.com> wrote: > > > > Allocas not in the entry block are treated as dynamic allocas and not > stack slots. > > > > > > On Sat, Apr 4, 2015, 8:37 PM Dave Pitsbawn <dpitsbawn at gmail.com> wrote: > > Here is some IR that is working and executing as expected -- All allocas > are in the first basic block, and only updates happen in other basic blocks. > > > > define i32 @f() { > > entry: > > %x = alloca i32 > > store i32 333, i32* %x > > %i = alloca i32 > > store i32 11, i32* %i > > br i1 true, label %if.then, label %if.else > > > > if.then: ; preds = %entry > > store i32 3, i32* %i > > %0 = load i32* %i > > ret i32 %0 > > > > if.else: ; preds = %entry > > ret i32 2 > > > > if.end: ; preds = %after_ret1, > %after_ > > ret > > ret i32 1 > > > > after_ret: ; No predecessors! > > br label %if.end > > > > after_ret1: ; No predecessors! > > br label %if.end > > > > after_ret2: ; No predecessors! > > ret i32 0 > > } > > > > The following IR is slightly different in that the alloca is defined not > in the first basic block: > > > > define i32 @M() { > > entry: > > %x = alloca i32 > > store i32 333, i32* %x > > br i1 true, label %if.then, label %if.else > > > > if.then: ; preds = %entry > > %i = alloca i32 > > store i32 3, i32* %i > > %0 = load i32* %i > > ret i32 %0 > > > > if.else: ; preds = %entry > > ret i32 2 > > > > if.end: ; preds = %after_ret1, > %after_ > > ret > > ret i32 1 > > > > after_ret: ; No predecessors! > > br label %if.end > > > > after_ret1: ; No predecessors! > > br label %if.end > > > > after_ret2: ; No predecessors! > > ret i32 0 > > } > > > > This segfaults for me. The IR passes the function verifier. Can someone > spot an error? I don't see any. > > _______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > _______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > _______________________________________________ > 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/20150405/64774ff1/attachment.html>
Thanks all. David why do you say it is particularly bad IR (other than not having gone through SROA). Is it the multiple blocks for early returns? That is how I'm supporting early returns in the middle of a basic block. I couldn't find any other way. On Sun, Apr 5, 2015 at 6:24 AM, David Jones <djones at xtreme-eda.com> wrote:> Data point: > > I use (rarely) alloca in basic blocks other than the entry block, and it > works. > > The one point to be aware of: alloca is "cleaned up" only when the > function returns. If you use alloca in a loop, and you have no other > mechanism to deal with it, you will blow out your stack and segfault. > > One way to deal with this is to use llvm.stacksave before the alloca ad > llvm.stackrestore after you're done. These functions can serve to do > "proper" middle-block allocations, creating temporary storage that is valid > only as long as you need it. > > Note to self: good call to do all of your "longer term" allocas in the > entry block. Don't move them to inner blocks even if you think you can, as > SROA won't touch them. > > > > On Sun, Apr 5, 2015 at 5:44 AM, David Chisnall < > David.Chisnall at cl.cam.ac.uk> wrote: > >> It's not great IR, but it doesn't look like it should actually crash, >> just (without SROA) produce comparatively bad code. The alloca is only >> referenced in the basic block that it exists. If this isn't expected to >> work, then we should probably improve the documentation of alloca in the >> language reference. >> >> David >> >> > On 5 Apr 2015, at 04:55, Eric Christopher <echristo at gmail.com> wrote: >> > >> > Allocas not in the entry block are treated as dynamic allocas and not >> stack slots. >> > >> > >> > On Sat, Apr 4, 2015, 8:37 PM Dave Pitsbawn <dpitsbawn at gmail.com> wrote: >> > Here is some IR that is working and executing as expected -- All >> allocas are in the first basic block, and only updates happen in other >> basic blocks. >> > >> > define i32 @f() { >> > entry: >> > %x = alloca i32 >> > store i32 333, i32* %x >> > %i = alloca i32 >> > store i32 11, i32* %i >> > br i1 true, label %if.then, label %if.else >> > >> > if.then: ; preds = %entry >> > store i32 3, i32* %i >> > %0 = load i32* %i >> > ret i32 %0 >> > >> > if.else: ; preds = %entry >> > ret i32 2 >> > >> > if.end: ; preds >> %after_ret1, %after_ >> > ret >> > ret i32 1 >> > >> > after_ret: ; No predecessors! >> > br label %if.end >> > >> > after_ret1: ; No predecessors! >> > br label %if.end >> > >> > after_ret2: ; No predecessors! >> > ret i32 0 >> > } >> > >> > The following IR is slightly different in that the alloca is defined >> not in the first basic block: >> > >> > define i32 @M() { >> > entry: >> > %x = alloca i32 >> > store i32 333, i32* %x >> > br i1 true, label %if.then, label %if.else >> > >> > if.then: ; preds = %entry >> > %i = alloca i32 >> > store i32 3, i32* %i >> > %0 = load i32* %i >> > ret i32 %0 >> > >> > if.else: ; preds = %entry >> > ret i32 2 >> > >> > if.end: ; preds >> %after_ret1, %after_ >> > ret >> > ret i32 1 >> > >> > after_ret: ; No predecessors! >> > br label %if.end >> > >> > after_ret1: ; No predecessors! >> > br label %if.end >> > >> > after_ret2: ; No predecessors! >> > ret i32 0 >> > } >> > >> > This segfaults for me. The IR passes the function verifier. Can someone >> spot an error? I don't see any. >> > _______________________________________________ >> > LLVM Developers mailing list >> > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> > _______________________________________________ >> > LLVM Developers mailing list >> > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> > > > _______________________________________________ > 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/20150405/f5698810/attachment.html>