[WebAssembly] Handle DebugLoc in DebugValueManager
authorHeejin Ahn <aheejin@gmail.com>
Mon, 27 Mar 2023 03:52:22 +0000 (20:52 -0700)
committerHeejin Ahn <aheejin@gmail.com>
Thu, 13 Apr 2023 06:47:24 +0000 (23:47 -0700)
According to
https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location,
when moving (and in our case cloning) within the same BB, the debug
location is preserved. But when moving / cloning to a different BB, we
preserve the debug location only if the destination BB contains the same
location. Currently we preserve the debug loc unconditionally in all
cases. This CL correctly handles the debug locs in DebugValueManager.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D148115

llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
llvm/test/DebugInfo/WebAssembly/dbg-loc-reg-stackify.mir [new file with mode: 0644]

index 90051d0..9e97e44 100644 (file)
@@ -226,6 +226,15 @@ bool WebAssemblyDebugValueManager::isInsertSamePlace(
   return true;
 }
 
+// Returns true if any instruction in MBB has the same debug location as DL.
+// Also returns true if DL is an empty location.
+static bool hasSameDebugLoc(const MachineBasicBlock *MBB, DebugLoc DL) {
+  for (const auto &MI : *MBB)
+    if (MI.getDebugLoc() == DL)
+      return true;
+  return false;
+}
+
 // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
 // 'Insert'. Convert the original DBG_VALUEs into undefs.
 //
@@ -263,6 +272,12 @@ void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) {
       getSinkableDebugValues(Insert);
 
   // Sink Def first.
+  //
+  // When moving to a different BB, we preserve the debug loc only if the
+  // destination BB contains the same location. See
+  // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
+  if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
+      Def->setDebugLoc(DebugLoc());
   MBB->splice(Insert, Def->getParent(), Def);
 
   if (DbgValues.empty())
@@ -344,6 +359,11 @@ void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert,
   // Clone Def first.
   if (CloneDef) {
     MachineInstr *Clone = MF->CloneMachineInstr(Def);
+    // When cloning to a different BB, we preserve the debug loc only if the
+    // destination BB contains the same location. See
+    // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
+    if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
+      Clone->setDebugLoc(DebugLoc());
     if (NewReg != CurrentReg && NewReg.isValid())
       Clone->getOperand(0).setReg(NewReg);
     MBB->insert(Insert, Clone);
diff --git a/llvm/test/DebugInfo/WebAssembly/dbg-loc-reg-stackify.mir b/llvm/test/DebugInfo/WebAssembly/dbg-loc-reg-stackify.mir
new file mode 100644 (file)
index 0000000..7b4b500
--- /dev/null
@@ -0,0 +1,125 @@
+# RUN: llc -run-pass wasm-reg-stackify %s -o - | FileCheck %s
+
+--- |
+  target triple = "wasm32-unknown-unknown"
+
+  declare void @use(i32)
+
+  define void @sink_same_bb() {
+    unreachable
+  }
+  define void @clone_same_bb() {
+    unreachable
+  }
+  define void @clone_different_bb_0() {
+    unreachable
+  }
+  define void @clone_different_bb_1() {
+    unreachable
+  }
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!2, !3, !4}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug)
+  !1 = !DIFile(filename: "test.c", directory: "")
+  !2 = !{i32 7, !"Dwarf Version", i32 5}
+  !3 = !{i32 2, !"Debug Info Version", i32 3}
+  !4 = !{i32 1, !"wchar_size", i32 4}
+  !6 = distinct !DISubprogram(name: "sink_same_bb", scope: !1, file: !1, line: 1, type: !7, scopeLine: 1, unit: !0)
+  !7 = !DISubroutineType(types: !8)
+  !8 = !{null}
+...
+
+---
+# Sinking within the same BB preserves the debug location.
+# CHECK-LABEL: name: sink_same_bb
+name: sink_same_bb
+liveins:
+  - { reg: '$arguments' }
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $arguments
+    %0:i32 = CONST_I32 1, implicit-def $arguments, debug-location !DILocation(line:10, scope:!6)
+    NOP implicit-def $arguments
+    CALL @use, %0:i32, implicit-def $arguments
+    RETURN implicit-def $arguments
+
+  ; CHECK:      %0:i32 = CONST_I32 1, {{.*}}, debug-location !DILocation(line: 10
+  ; CHECK-NEXT: CALL @use
+...
+
+---
+# Cloning within the same BB preserves the debug location.
+# CHECK-LABEL: name: clone_same_bb
+name: clone_same_bb
+liveins:
+  - { reg: '$arguments' }
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $arguments
+    %0:i32 = CONST_I32 1, implicit-def $arguments, debug-location !DILocation(line:10, scope:!6)
+    NOP implicit-def $arguments
+    CALL @use, %0:i32, implicit-def $arguments
+    CALL @use, %0:i32, implicit-def $arguments
+    RETURN implicit-def $arguments
+
+  ; CHECK:      CALL @use
+  ; CHECK-NEXT: %1:i32 = CONST_I32 1, {{.*}}, debug-location !DILocation(line: 10
+  ; CHECK-NEXT: CALL @use
+...
+
+---
+# Cloning to a different BB preserves the debug location in this case because
+# the destination BB has an instruction that has the same debug location
+# (test.c:10).
+# CHECK-LABEL: name: clone_different_bb_0
+name: clone_different_bb_0
+liveins:
+  - { reg: '$arguments' }
+tracksRegLiveness: true
+body: |
+  bb.0:
+    successors: %bb.1
+    liveins: $arguments
+    %0:i32 = CONST_I32 1, implicit-def $arguments, debug-location !DILocation(line:10, scope:!6)
+    BR %bb.1, implicit-def $arguments
+
+  bb.1:
+  ; predecessors: %bb.0
+    CALL @use, %0:i32, implicit-def $arguments, debug-location !DILocation(line:10, scope:!6)
+    RETURN implicit-def $arguments
+
+  ; CHECK: bb.1:
+  ; CHECK:      %1:i32 = CONST_I32 1, {{.*}}, debug-location !DILocation(line: 10
+  ; CHECK-NEXT: CALL @use, %1, {{.*}}, debug-location !DILocation(line: 10
+...
+
+---
+# Cloning to a different BB does NOT preserve the debug location in this case
+# because the destination BB doesn't have an instruction that has the same debug
+# location (It has test.c:20 but not test.c:10).
+# CHECK-LABEL: name: clone_different_bb_1
+name: clone_different_bb_1
+liveins:
+  - { reg: '$arguments' }
+tracksRegLiveness: true
+body: |
+  bb.0:
+    successors: %bb.1
+    liveins: $arguments
+    %0:i32 = CONST_I32 1, implicit-def $arguments, debug-location !DILocation(line:10, scope:!6)
+    BR %bb.1, implicit-def $arguments
+
+  bb.1:
+  ; predecessors: %bb.0
+    CALL @use, %0:i32, implicit-def $arguments, debug-location !DILocation(line:20, scope:!6)
+    RETURN implicit-def $arguments
+
+  ; CHECK: bb.1:
+  ; CHECK:      %1:i32 = CONST_I32 1
+  ; CHECK-NOT:  %1:i32 = CONST_I32 1, {{.*}}, debug-location !DILocation(line: 10
+  ; CHECK-NEXT: CALL @use, %1, {{.*}}, debug-location !DILocation(line: 20
+...