llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.1k stars 12.01k forks source link

Inliner sometimes produces invalid debug info #24248

Open dschuff opened 9 years ago

dschuff commented 9 years ago
Bugzilla Link 23874
Version trunk
OS Linux
Depends On llvm/llvm-project#23741
CC @dwblaikie,@dexonsmith,@echristo,@pogo59

Extended Description

I have an IR file with an approximate structure as follows. It has an inner and outer function with debug info and a middle function without debug info. The inner is inlined into the middle, and then the middle is inlined into the outer. After inlining when the module verifier visits the DISubprogram for the middle function, it checks the first instruction in middle (which originally came from inner), gets the inlinedAtScope, finds that it points to inner, and fails verification.

; Function Attrs: nounwind uwtable define void @​inner() #​0 { entry:

!dbg !​13 ret void, !dbg !​14 } ; Function Attrs: nounwind uwtable define void @​middle() #​0 { entry: call void @​inner() ret void } ; Function Attrs: nounwind uwtable define void @​outer() #​0 { entry: call void @​middle(), !dbg !​21 ret void, !dbg !​18 } I'm trying to figure out what the cause is; I tried building a simple reproducer from scratch similar to the above, but I can't reproduce it. I have attached a reproducer which is reduced by bugpoint; bugpoint did a pretty good job reducing the code but did nothing to the debug info, which is still huge, so I'm looking for some suggestions for making that smaller. I tried removing the !llvm.dbg.cu from the module; this had mostly the effect I was looking for, in causing most of the metadata to go away, but it also caused the problem to no longer reproduce. Any suggestions? notes on the reproducer: In the attached file, inner is _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSERKS5_, middle is _ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strERKNS_12basic_stringIcS2_S4_EE, and outer is _ZN7testing7MessageC2Ev To reproduce just run opt -inline bugpoint-reduced-simplified.bc The actual error is !dbg attachment points at wrong subprogram for function !​22062 = !DISubprogram(name: "str", linkageName: "_ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strERKNS_12basic_stringIcS2_S4_EE", scope: !"_ZTSNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEE", file: !​519, line: 453, type: !​15385, isLocal: false, isDefinition: true, scopeLine: 454, flags: DIFlagPrototyped, isOptimized: true, function: void (%"class.std::__1::basic_stringbuf.130.422.2573.3290.4485.5202.6875.8070.8787.10460.10699.10938.11416.12372.17258"*, %"class.std::__1::basic_string.5.297.2448.3165.4360.5077.6750.7945.8662.10335.10574.10813.11291.12247.17254"*)* @​_ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strERKNS_12basic_stringIcS2_S4_EE, declaration: !​15384, variables: !​22063) void (%"class.std::__1::basic_stringbuf.130.422.2573.3290.4485.5202.6875.8070.8787.10460.10699.10938.11416.12372.17258"*, %"class.std::__1::basic_string.5.297.2448.3165.4360.5077.6750.7945.8662.10335.10574.10813.11291.12247.17254"*)* @​_ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strERKNS_12basic_stringIcS2_S4_EE %cmp.i = icmp eq %"class.std::__1::basic_string.5.297.2448.3165.4360.5077.6750.7945.8662.10335.10574.10813.11291.12247.17254"* %__str_, %__s, !dbg !​91052 !​91057 = !DILocation(line: 2411, column: 14, scope: !​91058) !​91058 = distinct !DILexicalBlock(scope: !​59819, file: !​32233, line: 2411, column: 9) !​59819 = !DISubprogram(name: "operator=", linkageName: "_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSERKS5_", scope: !"_ZTSNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE", file: !​32233, line: 2409, type: !​53554, isLocal: false, isDefinition: true, scopeLine: 2410, flags: DIFlagPrototyped, isOptimized: true, function: void (%"class.std::__1::basic_string.5.297.2448.3165.4360.5077.6750.7945.8662.10335.10574.10813.11291.12247.17254"*, %"class.std::__1::basic_string.5.297.2448.3165.4360.5077.6750.7945.8662.10335.10574.10813.11291.12247.17254"*)* @​_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSERKS5_, declaration: !​58684, variables: !​59820) LLVM ERROR: Broken module found, compilation aborted!
3f18db19-85d0-42b5-b58f-dbfbd8cbce51 commented 9 years ago

Ah, that does sound like it could be an LTO bug:

Build one object (bitcode) file without debug info Build one object (bitcode) file with debug info.

Have the same comdat function in both.

Choose the non-debug-having implementation of the function, while keeping the subprogram debug info from the debug-having implementation.

Duncan, does that sound like a thing that can/would happen?

Yes, that sounds possible.

Once we put subprogram debug info as a function metadata attachment, would that fix this bug?

Yes, I think so. That's tracked by bug 23367, which I'm hoping to get back to soon (along with a bunch of follow-ups).

dwblaikie commented 9 years ago

Ah, that does sound like it could be an LTO bug:

Build one object (bitcode) file without debug info Build one object (bitcode) file with debug info.

Have the same comdat function in both.

Choose the non-debug-having implementation of the function, while keeping the subprogram debug info from the debug-having implementation.

Duncan, does that sound like a thing that can/would happen?

Once we put subprogram debug info as a function metadata attachment, would that fix this bug?

dschuff commented 9 years ago

In my linked bitcode file, there are some calls to middle which have dbg attachments (in this case from libgtest, which is built with debug info), and some calls which do not (other user files built without debug info). Middle is a comdat function, and the one included in the link output has no dbg attachments (presumably the copies from those files that were built with debug info had the attachments). There is also a DISubprogram for middle. I guess if the callee (middle) has no dbg attachements it should not have a DISubprogram? I guess I should look at the behavior of the linker in that case?

dschuff commented 9 years ago

This file is the result of a bitcode link of some files which have debug info (libc++) and some which do not (all the user files).

I'll try to see if the invariant you mentioned is getting violated in that process. It's also possible that one of the passes we run is dropping something it shouldn't.

dwblaikie commented 9 years ago

Hm, interesting. in my repro there is a DISubprogram for the middle function, but the function itself has no dbg attachments. Maybe that is the underlying unexpected thing?

Yes, that's likely to be a bad thing. The current requirement is that the call instruction must have a debug location if the caller and callee have debug info and the call site is inlinable.

If that requirement is violated => badness.

If you can create a small test case where that happens, that'd be great.

dschuff commented 9 years ago

Hm, interesting. in my repro there is a DISubprogram for the middle function, but the function itself has no dbg attachments. Maybe that is the underlying unexpected thing?

dwblaikie commented 9 years ago

There shouldn't be a DISubprogram for 'middle' then - so I'm not sure what the Verifier's visiting.

Perhaps it visited the instructions of 'middle' even though there was no DISubprogram - then compared the Function on the DISubprogram it reached from the instructions' debuglocs to the function the instructions were in and failed? That would be a bug in the verifier - it shouldn't inspect functions without DISubprograms.

dschuff commented 9 years ago

Thanks for the tips. The actual functions are reasonably well reduced, i'll try bisecting down the CUs and see what I can come up with. If that fails i'll go back to the source.

@​David: When the inner function gets inlined into middle, its instructions keep their debug info.

dwblaikie commented 9 years ago

another tip, once auto-reduction has stopped (& you've done all the obvious things that auto-reduction can't do - stripping templates and the like is one of the big ones creduce is still not very good at) you can try using alwaysinline attributes to force the inlining that the optimizer is doing anyway - then you can sometimes get back to an -O0 reproduction, jsut forcing the problematic inlining explicitly that way

3f18db19-85d0-42b5-b58f-dbfbd8cbce51 commented 9 years ago

I have attached a reproducer which is reduced by bugpoint; bugpoint did a pretty good job reducing the code but did nothing to the debug info, which is still huge, so I'm looking for some suggestions for making that smaller. I tried removing the !llvm.dbg.cu from the module; this had mostly the effect I was looking for, in causing most of the metadata to go away, but it also caused the problem to no longer reproduce.

Any suggestions?

Here's the rough algorithm I use.

  1. Check if the original source will reproduce with -gline-tables-only. If so, this is a better starting point because it skips all the type info.
  2. Try to reduce the preprocessed source with creduce and/or delta.
  3. Hand-reduce the original source, simplifying constructs that creduce has trouble folding away (usually member function or template related), and go back to step 2.

This is often good enough. But if I really just have bitcode (e.g., from a crash in a huge LTO) or the repro is still large, I continue:

  1. If there are multiple compile units in !llvm.dbg.cu, bisect which ones are necessary for the repro.
  2. If there are multiple entries in the remaining compile unit's subprograms: array, bisect which ones are necessary.
  3. Try to eliminate the rest of the arrays that the compile unit points at.

(Any time you make progress, you can round-trip to bitcode to garbage collect unreferenced metadata.)

dwblaikie commented 9 years ago

Derek - you describe the module verifier visiting the DISubprogram for the middle function. Yet you described the middle function as not having debug info. What's the deal there?

dschuff commented 9 years ago

File is too bug to upload. get it at https://drive.google.com/file/d/0B_T-_5p_VNCtMmYwZG90eWpWU0k/view?usp=sharing

llvmbot commented 1 year ago

@llvm/issue-subscribers-debuginfo