This is an archive of the discontinued LLVM Phabricator instance.

[DebugInfo][SROA] Correct debug info for global variables in case of SROA
ClosedPublic

Authored by alok on Mar 7 2022, 4:21 AM.

Details

Summary

The function transferSRADebugInfo is modified to include missing cases.

The existing handling produced crash for test case (attached with patch).

Please consider below IR

%struct.BSS1 = type <{ [12 x i8] }>
@.BSS1 = internal global %struct.BSS1 zeroinitializer, align 32, !dbg !0, !dbg !7, !dbg !10

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)

!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4))
!8 = distinct !DIGlobalVariable(name: "nodeb", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)

!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression(DW_OP_plus_uconst, 8))
!11 = distinct !DIGlobalVariable(name: "jmax", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)

In SROA @.BSS1 is broken into @.BSS1.0, @.BSS1.1, @.BSS1.2

@.BSS1.0 = internal unnamed_addr global i32 0, align 32, !dbg !0
@.BSS1.1 = internal unnamed_addr global i32 0, align 32, !dbg !14
@.BSS1.2 = internal unnamed_addr global i32 0, align 8, !dbg !15

Since original memory chunk is broken into three and each fragment directly maps to the three variables "nodea", "nodeb" and "jmax". So below DebugInfo should be generated.

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)
!14 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression())
!8 = distinct !DIGlobalVariable(name: "nodeb", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)
!15 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
!11 = distinct !DIGlobalVariable(name: "jmax", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)

But currently it was wrongly generating DW_OP_LLVM_fragment DIExpression and crashing later.

fragment covers entire variable
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 0, 32))
!1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !10, isLocal: true, isDefinition: true)
fragment is larger than or outside of variable
!15 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 32, 32))
!1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !10, isLocal: true, isDefinition: true)
fragment is larger than or outside of variable
!16 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 64, 32))
!1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !10, isLocal: true, isDefinition: true)

Later the verification fails as variable size same as fragment size which should be greater. Which leads a crash.

Breakpoint 2, (anonymous namespace)::Verifier::verifyFragmentExpression<llvm::DIGlobalVariableExpression const> (this=0x7fffffffb790, V=..., Fragment=...,
    Desc=0x555555712450) at /tmp/llvm-project/llvm/lib/IR/Verifier.cpp:5750
5750      AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V);
(gdb) p FragSize != *VarSize
$1 = false

Now the function transferSRADebugInfo is modified to

  • Ignore the current variable if it starts after the current Fragment
  • Ignore the current variable if it ends before the current Fragment
  • Generate (!DIExpression()) if current variable completely fits the current Fragment

Otherwise (as earlier), generate the DW_OP_LLVM_fragment in IR if current Fragment partially defines current variable.

Diff Detail

Event Timeline

alok created this revision.Mar 7 2022, 4:21 AM
Herald added a project: Restricted Project. · View Herald Transcript
alok requested review of this revision.Mar 7 2022, 4:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 7 2022, 4:22 AM

@alok Thanks for doing this! Can you please add a more descriptive summary of the change?

alok edited the summary of this revision. (Show Details)Mar 7 2022, 9:40 AM
alok edited the summary of this revision. (Show Details)Mar 7 2022, 9:43 AM

@alok Thanks for doing this! Can you please add a more descriptive summary of the change?

Thanks for your comment. I have updated the description now. Please check.

ormris removed a subscriber: ormris.Mar 7 2022, 9:53 AM
aprantl added inline comments.Mar 8 2022, 5:46 PM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
411

nit: can you end each sentence with a . for consistency?

414

This hardcoded 8 looks suspicious. What is it derived from and why is it a constant?

alok added inline comments.Mar 8 2022, 9:04 PM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
411

Thanks. I'll do that.

414

This is byte to bit conversion.

alok updated this revision to Diff 414008.Mar 8 2022, 9:55 PM

Re-based and updated to incorporate comments from @aprantl .

alok marked 2 inline comments as done.Mar 8 2022, 10:01 PM

Please wait for the other reviewers to be happy, but this LGTM with some nits addressed.

llvm/lib/Transforms/IPO/GlobalOpt.cpp
412–413

I think it is worth using DIExpression::extractIfOffset to get the offset here instead of inspecting the expression manually.

443

This is unrelated to your change but I am curious - sorry for the noise and possibly silly question. Should this return be a continue? cc @aprantl.

llvm/test/DebugInfo/Generic/global-sra-struct-fit-segment.ll
1 ↗(On Diff #414008)

Can you move this to llvm/test/DebugInfo/X86? The tests there only run if X86 is a registered target.

108 ↗(On Diff #414008)

Please can you replace the hardcoded metadata (!1, !8, !22) in these check lines?

djtodoro added inline comments.Mar 9 2022, 1:07 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
414

the CHAR_BIT is ok here

423

we have some extra parentheses here

llvm/test/DebugInfo/Generic/global-sra-struct-fit-segment.ll
99–101 ↗(On Diff #414008)

unused, so it can be deleted

108 ↗(On Diff #414008)

+1

alok added inline comments.Mar 9 2022, 2:10 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
423

Thanks. It will be removed in next version.

llvm/test/DebugInfo/Generic/global-sra-struct-fit-segment.ll
1 ↗(On Diff #414008)

Sure, it'll be moved.

99–101 ↗(On Diff #414008)

Sure, I'll be deleted.

108 ↗(On Diff #414008)

Sure, will do.

alok updated this revision to Diff 414040.Mar 9 2022, 2:11 AM

Re-based and updated to incorporate comments.

djtodoro added inline comments.Mar 9 2022, 2:13 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
416

this is new? should this be tested as well?

llvm/test/DebugInfo/X86/global-sra-struct-fit-segment.ll
21–24

this could also be deleted I guess

alok added inline comments.Mar 9 2022, 2:59 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
416

Adding test now.

llvm/test/DebugInfo/X86/global-sra-struct-fit-segment.ll
21–24

Sure, I will delete it.

alok updated this revision to Diff 414053.Mar 9 2022, 3:03 AM

Incorporated comments.

aprantl accepted this revision.Mar 9 2022, 8:54 AM
This revision is now accepted and ready to land.Mar 9 2022, 8:54 AM
This revision was landed with ongoing or failed builds.Mar 9 2022, 11:12 AM
This revision was automatically updated to reflect the committed changes.