David Blaikie
2014-Jun-07 20:03 UTC
[LLVMdev] -O0 inlining lost an alloca under subtle circumstances
Hi Chandler, In reducing a debug info test case I came across what looks like an odd variation in inlining output. Compiling the attached example produces the following IR for 'f7': define void @_Z2f7v() #0 { entry: %i.addr.i.i = alloca i32, align 4 %agg.tmp.i = alloca %struct.A, align 1 call void @llvm.dbg.declare(metadata !{null}, metadata !47) #3, !dbg !48 store i32 0, i32* %i.addr.i.i, align 4 call void @llvm.dbg.declare(metadata !{i32* %i.addr.i.i}, metadata !34) #3, !dbg !51 call void @_Z2f3v() #3, !dbg !51 ret void, !dbg !50 } If you comment out 'f3', you get this instead: define void @_Z2f7v() #0 { entry: %i.addr.i.i.i = alloca i32, align 4 %a.i.i = alloca %struct.A, align 1 %agg.tmp.i = alloca %struct.A, align 1 call void @llvm.dbg.declare(metadata !{%struct.A* %a.i.i}, metadata !45) #3, !dbg !46 store i32 0, i32* %i.addr.i.i.i, align 4 call void @llvm.dbg.declare(metadata !{i32* %i.addr.i.i.i}, metadata !33) #3, !dbg !49 call void @_Z2f3v() #3, !dbg !49 ret void, !dbg !48 } While debug info should cope with the dbg.declare with a null value in the first example, it... doesn't. (debug info is still /very/ much attached to those allocas). But in the second example, the alloca remains and the world is a happy place*. Any idea why this is happening? Should it be considered a bug in the inliner? (I haven't actually done all the IR pass-by-pass examination, but this is coming out of Clang -O0 with a few always_inline attributes, so I'm not sure there's much else at work here, especially given how this is affected by other functions that are never inlined anywhere - all that talk of strongly connected components in the call graph is starting to feel vaguely familiar here) - David * the specific description of how this affects debug info is this: The first time we see the inlined function, we create the abstract definition but since the alloca was dropped, we don't include that variable in the abstract definition (above -O0, the frontend emits a list of all the variables in the function, and we use that to recover from cases where variables are optimized away - at -O0, this doesn't happen because we assume the allocas are preserved, etc). Later on, another function gets this inlined and /does/ have the variable, it assumes that since the abstract definition has been constructed, so have all the abstract variables... but that's evidently not the case and it fires the assert I've been trying to enable for the last couple of weeks. (though even if it weren't for the assert, it'd still cause incorrect debug info, because we're missing some of the abstract variables) -------------- next part -------------- A non-text attachment was scrubbed... Name: missing_abstract.cpp Type: text/x-c++src Size: 393 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140607/440fa129/attachment.cpp>
David Blaikie
2014-Aug-08 18:00 UTC
[LLVMdev] -O0 inlining lost an alloca under subtle circumstances
Ping On Sat, Jun 7, 2014 at 1:03 PM, David Blaikie <dblaikie at gmail.com> wrote:> Hi Chandler, > > In reducing a debug info test case I came across what looks like an > odd variation in inlining output. > > Compiling the attached example produces the following IR for 'f7': > > define void @_Z2f7v() #0 { > entry: > %i.addr.i.i = alloca i32, align 4 > %agg.tmp.i = alloca %struct.A, align 1 > call void @llvm.dbg.declare(metadata !{null}, metadata !47) #3, !dbg !48 > store i32 0, i32* %i.addr.i.i, align 4 > call void @llvm.dbg.declare(metadata !{i32* %i.addr.i.i}, metadata > !34) #3, !dbg !51 > call void @_Z2f3v() #3, !dbg !51 > ret void, !dbg !50 > } > > If you comment out 'f3', you get this instead: > > define void @_Z2f7v() #0 { > entry: > %i.addr.i.i.i = alloca i32, align 4 > %a.i.i = alloca %struct.A, align 1 > %agg.tmp.i = alloca %struct.A, align 1 > call void @llvm.dbg.declare(metadata !{%struct.A* %a.i.i}, > metadata !45) #3, !dbg !46 > store i32 0, i32* %i.addr.i.i.i, align 4 > call void @llvm.dbg.declare(metadata !{i32* %i.addr.i.i.i}, > metadata !33) #3, !dbg !49 > call void @_Z2f3v() #3, !dbg !49 > ret void, !dbg !48 > } > > While debug info should cope with the dbg.declare with a null value in > the first example, it... doesn't. (debug info is still /very/ much > attached to those allocas). But in the second example, the alloca > remains and the world is a happy place*. > > Any idea why this is happening? Should it be considered a bug in the > inliner? (I haven't actually done all the IR pass-by-pass examination, > but this is coming out of Clang -O0 with a few always_inline > attributes, so I'm not sure there's much else at work here, especially > given how this is affected by other functions that are never inlined > anywhere - all that talk of strongly connected components in the call > graph is starting to feel vaguely familiar here) > > - David > > * the specific description of how this affects debug info is this: The > first time we see the inlined function, we create the abstract > definition but since the alloca was dropped, we don't include that > variable in the abstract definition (above -O0, the frontend emits a > list of all the variables in the function, and we use that to recover > from cases where variables are optimized away - at -O0, this doesn't > happen because we assume the allocas are preserved, etc). Later on, > another function gets this inlined and /does/ have the variable, it > assumes that since the abstract definition has been constructed, so > have all the abstract variables... but that's evidently not the case > and it fires the assert I've been trying to enable for the last couple > of weeks. (though even if it weren't for the assert, it'd still cause > incorrect debug info, because we're missing some of the abstract > variables)