[llvm] [InstrRef] Skip clobbered EntryValue register recovery (PR #77938)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 12 07:29:07 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

Author: Felipe de Azevedo Piovezan (felipepiovezan)

<details>
<summary>Changes</summary>

This changes the final stage of InstrRef, i.e. the TransferTracker (which combines the values locations with the variable values), so that it treats a DEBUG_VALUE of an EntryValue just like a DEBUG_VALUE of a constant: a location that is never clobbered and can be propagated to subsequent BBs as long as no other DEBUG_VALUE intrinsics updated the variable.

We add two tests here:

1. `entry_value_clobbered_stack_copy` that saves a register on the stack, uses this register as an entry value DBG_VALUE location, and then clobbers it. Prior to this patch, this test would crash because we would try to describe a new location for the variable in terms of what was saved on the stack, and use an invalid expression to do so. This is not needed as an EntryValue can never be clobbered.

2. `entry_value_gets_propagated`, that tests that an EntryValue DBG_VALUE is propagated in a diamond-shaped CFG. This test works with or without this patch, but it reveals a bug (see the FIXME), where the propagation doesn't happen if the register gets clobbered. This same test (with the clobbered register) works fine in the VarLoc implementation of LDV.

---
Full diff: https://github.com/llvm/llvm-project/pull/77938.diff


3 Files Affected:

- (modified) llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp (+1) 
- (added) llvm/test/DebugInfo/MIR/InstrRef/entry_value_clobbered_stack_copy.mir (+53) 
- (added) llvm/test/DebugInfo/MIR/InstrRef/entry_value_gets_propagated.mir (+102) 


``````````diff
diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
index cfc8c28b99e562..71a0255bf36e17 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
@@ -670,6 +670,7 @@ class TransferTracker {
 
     // Ignore non-register locations, we don't transfer those.
     if (MI.isUndefDebugValue() ||
+        MI.getDebugExpression()->isEntryValue() ||
         all_of(MI.debug_operands(),
                [](const MachineOperand &MO) { return !MO.isReg(); })) {
       auto It = ActiveVLocs.find(Var);
diff --git a/llvm/test/DebugInfo/MIR/InstrRef/entry_value_clobbered_stack_copy.mir b/llvm/test/DebugInfo/MIR/InstrRef/entry_value_clobbered_stack_copy.mir
new file mode 100644
index 00000000000000..1280045a0a1cf1
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/entry_value_clobbered_stack_copy.mir
@@ -0,0 +1,53 @@
+# RUN: llc --run-pass=livedebugvalues -o - %s | FileCheck %s
+# REQUIRES: x86-registered-target
+
+--- |
+  target triple = "x86_64-"
+  define void @foo(ptr swiftasync %0) !dbg !4 {
+    call void @llvm.dbg.value(metadata ptr %0, metadata !9, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !17
+    ret void
+  }
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  !llvm.module.flags = !{!0}
+  !llvm.dbg.cu = !{!1}
+
+  !0 = !{i32 2, !"Debug Info Version", i32 3}
+  !1 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !2, producer: "blah", isOptimized: true, flags: "blah", runtimeVersion: 5, emissionKind: FullDebug)
+  !2 = !DIFile(filename: "blah", directory: "blah")
+  !3 = !{}
+  !4 = distinct !DISubprogram(name: "blah", linkageName: "blah", scope: !2, file: !2, line: 284, type: !7, unit: !1)
+  !7 = !DISubroutineType(types: !3)
+  !9 = !DILocalVariable(name: "self", arg: 3, scope: !4, file: !2, line: 328, type: !12, flags: DIFlagArtificial)
+  !12 = !DICompositeType(tag: DW_TAG_structure_type, name: "blah", scope: !2, file: !2, size: 64, elements: !3)
+  !17 = !DILocation(line: 328, column: 17, scope: !4)
+
+...
+---
+name:            foo
+alignment:       16
+debugInstrRef:   true
+tracksDebugUserValues: true
+liveins:
+  - { reg: '$r14', virtual-reg: '' }
+stack:
+  - { id: 0, name: '', type: spill-slot, offset: -64, size: 8, alignment: 8,
+      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.0:
+    liveins: $r14
+
+    ; Put a copy of r14 on the stack.
+    MOV64mr $rbp, 1, $noreg, -48, $noreg, $r14 :: (store (s64) into %stack.0)
+    DBG_VALUE $r14, $noreg, !9, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !17
+    MOV64mi32 $noreg, 1, $noreg, 0, $noreg, 0, debug-location !17 :: (store (s64) into `ptr null`)
+    $r14 = MOV64rr killed $r13
+    ; Clobber $r14
+    RETI64 24
+
+# CHECK: bb.0:
+# CHECK:      MOV64mr $rbp, 1, $noreg, -48, $noreg, $r14
+# CHECK-NEXT: DBG_VALUE $r14, {{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
+# CHECK-NOT:  DBG_VALUE
+...
diff --git a/llvm/test/DebugInfo/MIR/InstrRef/entry_value_gets_propagated.mir b/llvm/test/DebugInfo/MIR/InstrRef/entry_value_gets_propagated.mir
new file mode 100644
index 00000000000000..4fa1485a75d2ce
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/InstrRef/entry_value_gets_propagated.mir
@@ -0,0 +1,102 @@
+# RUN: llc --run-pass=livedebugvalues -o - %s | FileCheck %s
+# REQUIRES: x86-registered-target
+--- |
+  target triple = "x86_64-"
+
+  define i32 @baz(i32 swiftasync %arg1, i32 noundef %arg2, i1 %cond) !dbg !9 {
+    tail call void @llvm.dbg.value(metadata i32 %arg1, metadata !17, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !19
+    br i1 %cond, label %if.then, label %if.else, !dbg !22
+  if.then:
+    %call = call i32 @foo(i32 noundef %arg1), !dbg !23
+    br label %if.end, !dbg !25
+  if.else:
+    %call1 = call i32 @foo(i32 noundef %arg2), !dbg !26
+    br label %if.end
+  if.end:
+    %temp.0 = phi i32 [ %call, %if.then ], [ %call1, %if.else ], !dbg !28
+    ret i32 %temp.0, !dbg !29
+  }
+
+  declare i32 @foo(i32)
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!2, !3}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "ha", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+  !1 = !DIFile(filename: "test.c", directory: "hah")
+  !2 = !{i32 7, !"Dwarf Version", i32 4}
+  !3 = !{i32 2, !"Debug Info Version", i32 3}
+  !9 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 3, type: !10, scopeLine: 3, unit: !0, retainedNodes: !13)
+  !10 = !DISubroutineType(types: !11)
+  !11 = !{!12, !12, !12, !12}
+  !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !13 = !{!14, !15, !16, !17}
+  !14 = !DILocalVariable(name: "arg1", arg: 1, scope: !9, file: !1, line: 3, type: !12)
+  !15 = !DILocalVariable(name: "arg2", arg: 2, scope: !9, file: !1, line: 3, type: !12)
+  !16 = !DILocalVariable(name: "cond", arg: 3, scope: !9, file: !1, line: 3, type: !12)
+  !17 = !DILocalVariable(name: "local", scope: !9, file: !1, line: 4, type: !12)
+  !19 = !DILocation(line: 0, scope: !9)
+  !20 = !DILocation(line: 7, column: 7, scope: !21)
+  !21 = distinct !DILexicalBlock(scope: !9, file: !1, line: 7, column: 7)
+  !22 = !DILocation(line: 7, column: 7, scope: !9)
+  !23 = !DILocation(line: 8, column: 12, scope: !24)
+  !24 = distinct !DILexicalBlock(scope: !21, file: !1, line: 7, column: 13)
+  !25 = !DILocation(line: 9, column: 3, scope: !24)
+  !26 = !DILocation(line: 10, column: 12, scope: !27)
+  !27 = distinct !DILexicalBlock(scope: !21, file: !1, line: 9, column: 10)
+  !28 = !DILocation(line: 0, scope: !21)
+  !29 = !DILocation(line: 13, column: 3, scope: !9)
+
+...
+---
+name:            baz
+alignment:       16
+debugInstrRef: true
+tracksDebugUserValues: true
+liveins:
+  - { reg: '$r14', virtual-reg: '' }
+  - { reg: '$edi', virtual-reg: '' }
+  - { reg: '$esi', virtual-reg: '' }
+  - { reg: '$edx', virtual-reg: '' }
+body:             |
+  bb.0:
+    successors: %bb.2(0x40000000), %bb.1(0x40000000)
+    liveins: $r14, $edi, $edx, $esi
+
+    DBG_VALUE $r14, $noreg, !14, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !19
+    ; FIXME: InstrRef is not yet capable of propagating these when the entry
+    ; value register is clobbered.
+    ;$r14 = MOV64ri 0, debug-location !20
+    CMP32ri killed renamable $edx, 0, implicit-def $eflags, debug-location !20
+    JCC_1 %bb.2, 4, implicit killed $eflags, debug-location !22
+
+  bb.1.if.then:
+    successors: %bb.3(0x80000000)
+    liveins: $edi, $r13
+
+    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $eax, debug-location !23
+    JMP_1 %bb.3, debug-location !25
+
+  bb.2.if.else:
+    successors: %bb.3(0x80000000)
+    liveins: $esi, $r13
+
+    $edi = MOV32rr killed $esi, debug-location !26
+    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $eax, debug-location !26
+
+  bb.3.if.end:
+    liveins: $eax
+
+    $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !29
+    RET64 implicit $eax, debug-location !29
+
+# CHECK-LABEL: bb.0:
+# CHECK: DBG_VALUE $r14, {{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
+# CHECK-LABEL: bb.1.if.then:
+# CHECK: DBG_VALUE $r14, {{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
+# CHECK-LABEL: bb.2.if.else:
+# CHECK: DBG_VALUE $r14, {{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
+# CHECK-LABEL: bb.3.if.end:
+# CHECK: DBG_VALUE $r14, {{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/77938


More information about the llvm-commits mailing list