[llvm] e9ea7a0 - [WebAssembly] Use LiveDebugValues analysis

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 10 09:55:44 PST 2023


Author: Heejin Ahn
Date: 2023-01-10T09:54:59-08:00
New Revision: e9ea7a0e20c27dc080dc16dc4b7c5c104801fe69

URL: https://github.com/llvm/llvm-project/commit/e9ea7a0e20c27dc080dc16dc4b7c5c104801fe69
DIFF: https://github.com/llvm/llvm-project/commit/e9ea7a0e20c27dc080dc16dc4b7c5c104801fe69.diff

LOG: [WebAssembly] Use LiveDebugValues analysis

This enables `LiveDebugValues` analysis for Wasm. `DBG_VALUE`s expire at
the end of a BB, and this is the analysis extends their lifetime when
possible, greatly increasing the coverage of variable debug info.

Specifically, this removes the current constraint that this analysis is
only used with physical registers, which was first introduced in D18421,
because Wasm uses only virtual registers. I don't think there's anything
inherent in this analysis that only applies to physical registers; it
was just because all targets using this analysis ran this at the end of
their compiliation pipeline, at which point all their vregs had been
allocated, and Wasm's debug info infrastructure was not really set up
yet, so it was not using it.

This adds supports to Wasm-specific target-index operands, defined in
https://github.com/llvm/llvm-project/blob/2166d9529a60d1cdedb733d2e4134c971f0969ec/llvm/lib/Target/WebAssembly/WebAssembly.h#L87-L100.
Among these, `TI_LOCAL`, `TI_LOCAL_INDIRECT`, and `TI_OPERAND_STACK` are
used by Wasm `DBG_VALUE` instructions.

This does not yet handle mutable target indices, i.e., this does not
terminate a `DBG_VALUE` for a local index when we encounter a new
`local.set` or `local.tee`. It will be implemented as a follow-up.

Reviewed By: dschuff, jmorse

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

Added: 
    llvm/test/DebugInfo/WebAssembly/live-debug-values.mir

Modified: 
    llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
    llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
index 141008ac2296a..9dba9a88f7031 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Pass.h"
 #include "llvm/PassRegistry.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetMachine.h"
 
 /// \file LiveDebugValues.cpp
 ///
@@ -72,11 +73,6 @@ class LiveDebugValues : public MachineFunctionPass {
   /// Calculate the liveness information for the given machine function.
   bool runOnMachineFunction(MachineFunction &MF) override;
 
-  MachineFunctionProperties getRequiredProperties() const override {
-    return MachineFunctionProperties().set(
-        MachineFunctionProperties::Property::NoVRegs);
-  }
-
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.setPreservesCFG();
     MachineFunctionPass::getAnalysisUsage(AU);
@@ -106,6 +102,14 @@ LiveDebugValues::LiveDebugValues() : MachineFunctionPass(ID) {
 }
 
 bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) {
+  // Except for Wasm, all targets should be only using physical register at this
+  // point. Wasm only use virtual registers throught its pipeline, but its
+  // virtual registers don't participate  in this LiveDebugValues analysis; only
+  // its target indices do.
+  assert(MF.getTarget().getTargetTriple().isWasm() ||
+         MF.getProperties().hasProperty(
+             MachineFunctionProperties::Property::NoVRegs));
+
   bool InstrRefBased = MF.useDebugInstrRef();
   // Allow the user to force selection of InstrRef LDV.
   InstrRefBased |= ForceInstrRefLDV;

diff  --git a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp
index 9686f8215d702..062b5f5e2a91d 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp
@@ -299,6 +299,16 @@ class VarLocBasedLDV : public LDVImpl {
       }
     };
 
+    // Target indices used for wasm-specific locations.
+    struct WasmLoc {
+      int Index; // One of TargetIndex values defined in WebAssembly.h
+      int64_t Offset;
+      bool operator==(const WasmLoc &Other) const {
+        return Index == Other.Index && Offset == Other.Offset;
+      }
+      bool operator!=(const WasmLoc &Other) const { return !(*this == Other); }
+    };
+
     /// Identity of the variable at this location.
     const DebugVariable Var;
 
@@ -313,7 +323,8 @@ class VarLocBasedLDV : public LDVImpl {
       InvalidKind = 0,
       RegisterKind,
       SpillLocKind,
-      ImmediateKind
+      ImmediateKind,
+      WasmLocKind
     };
 
     enum class EntryValueLocKind {
@@ -332,6 +343,7 @@ class VarLocBasedLDV : public LDVImpl {
       int64_t Immediate;
       const ConstantFP *FPImm;
       const ConstantInt *CImm;
+      WasmLoc WasmLocation;
       MachineLocValue() : Hash(0) {}
     };
 
@@ -348,6 +360,8 @@ class VarLocBasedLDV : public LDVImpl {
         switch (Kind) {
         case MachineLocKind::SpillLocKind:
           return Value.SpillLocation == Other.Value.SpillLocation;
+        case MachineLocKind::WasmLocKind:
+          return Value.WasmLocation == Other.Value.WasmLocation;
         case MachineLocKind::RegisterKind:
         case MachineLocKind::ImmediateKind:
           return Value.Hash == Other.Value.Hash;
@@ -366,6 +380,11 @@ class VarLocBasedLDV : public LDVImpl {
                      Other.Kind, Other.Value.SpillLocation.SpillBase,
                      Other.Value.SpillLocation.SpillOffset.getFixed(),
                      Other.Value.SpillLocation.SpillOffset.getScalable());
+        case MachineLocKind::WasmLocKind:
+          return std::make_tuple(Kind, Value.WasmLocation.Index,
+                                 Value.WasmLocation.Offset) <
+                 std::make_tuple(Other.Kind, Other.Value.WasmLocation.Index,
+                                 Other.Value.WasmLocation.Offset);
         case MachineLocKind::RegisterKind:
         case MachineLocKind::ImmediateKind:
           return std::tie(Kind, Value.Hash) <
@@ -429,6 +448,9 @@ class VarLocBasedLDV : public LDVImpl {
       } else if (Op.isCImm()) {
         Kind = MachineLocKind::ImmediateKind;
         Loc.CImm = Op.getCImm();
+      } else if (Op.isTargetIndex()) {
+        Kind = MachineLocKind::WasmLocKind;
+        Loc.WasmLocation = {Op.getIndex(), Op.getOffset()};
       } else
         llvm_unreachable("Invalid Op kind for MachineLoc.");
       return {Kind, Loc};
@@ -562,6 +584,10 @@ class VarLocBasedLDV : public LDVImpl {
           MOs.push_back(Orig);
           break;
         }
+        case MachineLocKind::WasmLocKind: {
+          MOs.push_back(Orig);
+          break;
+        }
         case MachineLocKind::InvalidKind:
           llvm_unreachable("Tried to produce DBG_VALUE for invalid VarLoc");
         }
@@ -654,8 +680,9 @@ class VarLocBasedLDV : public LDVImpl {
     }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-    // TRI can be null.
-    void dump(const TargetRegisterInfo *TRI, raw_ostream &Out = dbgs()) const {
+    // TRI and TII can be null.
+    void dump(const TargetRegisterInfo *TRI, const TargetInstrInfo *TII,
+              raw_ostream &Out = dbgs()) const {
       Out << "VarLoc(";
       for (const MachineLoc &MLoc : Locs) {
         if (Locs.begin() != &MLoc)
@@ -674,6 +701,22 @@ class VarLocBasedLDV : public LDVImpl {
         case MachineLocKind::ImmediateKind:
           Out << MLoc.Value.Immediate;
           break;
+        case MachineLocKind::WasmLocKind: {
+          if (TII) {
+            auto Indices = TII->getSerializableTargetIndices();
+            auto Found =
+                find_if(Indices, [&](const std::pair<int, const char *> &I) {
+                  return I.first == MLoc.Value.WasmLocation.Index;
+                });
+            assert(Found != Indices.end());
+            Out << Found->second;
+            if (MLoc.Value.WasmLocation.Offset > 0)
+              Out << " + " << MLoc.Value.WasmLocation.Offset;
+          } else {
+            Out << "WasmLoc";
+          }
+          break;
+        }
         case MachineLocKind::InvalidKind:
           llvm_unreachable("Invalid VarLoc in dump method");
         }
@@ -1201,7 +1244,7 @@ void VarLocBasedLDV::printVarLocInMBB(const MachineFunction &MF,
     for (const VarLoc &VL : VarLocs) {
       Out << " Var: " << VL.Var.getVariable()->getName();
       Out << " MI: ";
-      VL.dump(TRI, Out);
+      VL.dump(TRI, TII, Out);
     }
   }
   Out << "\n";
@@ -1339,7 +1382,7 @@ void VarLocBasedLDV::transferDebugValue(const MachineInstr &MI,
 
   if (all_of(MI.debug_operands(), [](const MachineOperand &MO) {
         return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
-               MO.isCImm();
+               MO.isCImm() || MO.isTargetIndex();
       })) {
     // Use normal VarLoc constructor for registers and immediates.
     VarLoc VL(MI);
@@ -1452,7 +1495,7 @@ void VarLocBasedLDV::insertTransferDebugPair(
     ProcessVarLoc(VL);
     LLVM_DEBUG({
       dbgs() << "Creating VarLoc for register copy:";
-      VL.dump(TRI);
+      VL.dump(TRI, TII);
     });
     return;
   }
@@ -1465,7 +1508,7 @@ void VarLocBasedLDV::insertTransferDebugPair(
     ProcessVarLoc(VL);
     LLVM_DEBUG({
       dbgs() << "Creating VarLoc for spill:";
-      VL.dump(TRI);
+      VL.dump(TRI, TII);
     });
     return;
   }
@@ -1478,7 +1521,7 @@ void VarLocBasedLDV::insertTransferDebugPair(
     ProcessVarLoc(VL);
     LLVM_DEBUG({
       dbgs() << "Creating VarLoc for restore:";
-      VL.dump(TRI);
+      VL.dump(TRI, TII);
     });
     return;
   }
@@ -1816,7 +1859,7 @@ bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,
     for (VarLoc &VL : VarLocs) {
       // Copy OpenRanges to OutLocs, if not already present.
       dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ":  ";
-      VL.dump(TRI);
+      VL.dump(TRI, TII);
     }
   });
   VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
@@ -2056,10 +2099,14 @@ bool VarLocBasedLDV::isEntryValueCandidate(
 /// Collect all register defines (including aliases) for the given instruction.
 static void collectRegDefs(const MachineInstr &MI, DefinedRegsSet &Regs,
                            const TargetRegisterInfo *TRI) {
-  for (const MachineOperand &MO : MI.operands())
-    if (MO.isReg() && MO.isDef() && MO.getReg())
+  for (const MachineOperand &MO : MI.operands()) {
+    if (MO.isReg() && MO.isDef() && MO.getReg() &&
+        Register::isPhysicalRegister(MO.getReg())) {
+      Regs.insert(MO.getReg());
       for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
         Regs.insert(*AI);
+    }
+  }
 }
 
 /// This routine records the entry values of function parameters. The values
@@ -2100,7 +2147,7 @@ bool VarLocBasedLDV::ExtendRanges(MachineFunction &MF,
                                   TargetPassConfig *TPC, unsigned InputBBLimit,
                                   unsigned InputDbgValLimit) {
   (void)DomTree;
-  LLVM_DEBUG(dbgs() << "\nDebug Range Extension\n");
+  LLVM_DEBUG(dbgs() << "\nDebug Range Extension: " << MF.getName() << "\n");
 
   if (!MF.getFunction().getSubprogram())
     // VarLocBaseLDV will already have removed all DBG_VALUEs.

diff  --git a/llvm/test/DebugInfo/WebAssembly/live-debug-values.mir b/llvm/test/DebugInfo/WebAssembly/live-debug-values.mir
new file mode 100644
index 0000000000000..6a854a3d0bf1e
--- /dev/null
+++ b/llvm/test/DebugInfo/WebAssembly/live-debug-values.mir
@@ -0,0 +1,181 @@
+# RUN: llc -run-pass livedebugvalues %s -o - | FileCheck %s
+
+# Test if LiveDebugValue analysis works on Wasm.
+
+--- |
+  target triple = "wasm32-unknown-unknown"
+
+  define void @test_consts() !dbg !5 {
+    call void @llvm.dbg.value(metadata i32 0, metadata !9, metadata !DIExpression()), !dbg !10
+    call void @llvm.dbg.value(metadata i32 0, metadata !11, metadata !DIExpression()), !dbg !10
+    call void @llvm.dbg.value(metadata i32 0, metadata !12, metadata !DIExpression()), !dbg !10
+    call void @llvm.dbg.value(metadata i32 0, metadata !13, metadata !DIExpression()), !dbg !10
+    ret void
+  }
+
+  define void @test_target_indices() !dbg !14 {
+    call void @llvm.dbg.value(metadata i32 0, metadata !15, metadata !DIExpression()), !dbg !16
+    call void @llvm.dbg.value(metadata i32 0, metadata !17, metadata !DIExpression()), !dbg !16
+    call void @llvm.dbg.value(metadata i32 0, metadata !18, metadata !DIExpression()), !dbg !16
+    call void @llvm.dbg.value(metadata i32 0, metadata !19, metadata !DIExpression()), !dbg !16
+    call void @llvm.dbg.value(metadata i32 0, metadata !20, metadata !DIExpression()), !dbg !16
+    ret void
+  }
+
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  !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}
+  !5 = distinct !DISubprogram(name: "test_consts", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, unit: !0)
+  ; CHECK: ![[T0_SP:[0-9]+]] = distinct !DISubprogram(name: "test_consts"
+  !6 = !DISubroutineType(types: !7)
+  !7 = !{!8}
+  !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !9 = !DILocalVariable(name: "var0", scope: !5, file: !1, line: 2, type: !8)
+  ; CHECK: ![[T0_VAR0:[0-9]+]] = !DILocalVariable(name: "var0", scope: ![[T0_SP]]
+  !10 = !DILocation(line: 0, scope: !5)
+  !11 = !DILocalVariable(name: "var1", scope: !5, file: !1, line: 2, type: !8)
+  ; CHECK: ![[T0_VAR1:[0-9]+]] = !DILocalVariable(name: "var1", scope: ![[T0_SP]]
+  !12 = !DILocalVariable(name: "var2", scope: !5, file: !1, line: 2, type: !8)
+  ; CHECK: ![[T0_VAR2:[0-9]+]] = !DILocalVariable(name: "var2", scope: ![[T0_SP]]
+  !13 = !DILocalVariable(name: "var3", scope: !5, file: !1, line: 2, type: !8)
+  ; CHECK: ![[T0_VAR3:[0-9]+]] = !DILocalVariable(name: "var3", scope: ![[T0_SP]]
+  !14 = distinct !DISubprogram(name: "test_target_indices", scope: !1, file: !1, line: 10, type: !6, scopeLine: 1, unit: !0)
+  ; CHECK: ![[T1_SP:[0-9]+]] = distinct !DISubprogram(name: "test_target_indices"
+  !15 = !DILocalVariable(name: "var0", scope: !14, file: !1, line: 11, type: !8)
+  ; CHECK: ![[T1_VAR0:[0-9]+]] = !DILocalVariable(name: "var0", scope: ![[T1_SP]]
+  !16 = !DILocation(line: 10, scope: !14)
+  !17 = !DILocalVariable(name: "var1", scope: !14, file: !1, line: 11, type: !8)
+  ; CHECK: ![[T1_VAR1:[0-9]+]] = !DILocalVariable(name: "var1", scope: ![[T1_SP]]
+  !18 = !DILocalVariable(name: "var2", scope: !14, file: !1, line: 11, type: !8)
+  ; CHECK: ![[T1_VAR2:[0-9]+]] = !DILocalVariable(name: "var2", scope: ![[T1_SP]]
+  !19 = !DILocalVariable(name: "var3", scope: !14, file: !1, line: 11, type: !8)
+  ; CHECK: ![[T1_VAR3:[0-9]+]] = !DILocalVariable(name: "var3", scope: ![[T1_SP]]
+  !20 = !DILocalVariable(name: "var4", scope: !14, file: !1, line: 11, type: !8)
+  ; CHECK: ![[T1_VAR4:[0-9]+]] = !DILocalVariable(name: "var4", scope: ![[T1_SP]]
+...
+
+---
+# var0: Its debug value is set once in bb.0 and valid throughout the function.
+#       So a new DBG_VALUE will be added to the beginnings of all other BBs
+#       (bb.1, bb.2, and bb.3).
+# var1: Its debug value is set in bb.0, but is reset to no info in bb.1. So a
+#       new DBG_VALUE will be added in the beginning of bb.1 and bb.2, but bb.3
+#       will not, because its two predecesors (bb.1 and bb.2) have 
diff erent
+#       debug values.
+# var2: Its debug value is set both in bb.1 and bb.2 with the same value. bb.3
+#       will have a new DBG_VALUE representing that value.
+# var3: Its debug value is set both in bb.1 and bb.2 but with 
diff erent values.
+#       bb.3 will NOT have a new DBG_VALUE instruction because its predecessors
+#       don't agree on a value.
+# CHECK-LABEL: name: test_consts
+name: test_consts
+liveins:
+  - { reg: '$arguments' }
+body: |
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $arguments
+    DBG_VALUE 10, $noreg, !9, !DIExpression(), debug-location !10
+    DBG_VALUE 20, $noreg, !11, !DIExpression(), debug-location !10
+    %0:i32 = CONST_I32 1, implicit-def $arguments
+    BR_IF %bb.2, %0:i32, implicit-def $arguments
+
+  ; CHECK: bb.1:
+  ; CHECK-DAG: DBG_VALUE 10, $noreg, ![[T0_VAR0]]
+  ; CHECK-DAG: DBG_VALUE 20, $noreg, ![[T0_VAR1]]
+  bb.1:
+  ; predecessors: %bb.0
+    successors: %bb.3
+    DBG_VALUE $noreg, $noreg, !11, !DIExpression(), debug-location !10
+    DBG_VALUE 30, $noreg, !12, !DIExpression(), debug-location !10
+    DBG_VALUE 30, $noreg, !13, !DIExpression(), debug-location !10
+    BR %bb.3, implicit-def $arguments
+
+  ; CHECK: bb.2:
+  ; CHECK-DAG: DBG_VALUE 10, $noreg, ![[T0_VAR0]]
+  ; CHECK-DAG: DBG_VALUE 20, $noreg, ![[T0_VAR1]]
+  bb.2:
+  ; predecessors: %bb.0
+    successors: %bb.3
+    DBG_VALUE 30, $noreg, !12, !DIExpression(), debug-location !10
+    DBG_VALUE 40, $noreg, !13, !DIExpression(), debug-location !10
+    BR %bb.3, implicit-def $arguments
+
+  ; CHECK: bb.3:
+  ; CHECK-DAG: DBG_VALUE 10, $noreg, ![[T0_VAR0]]
+  ; CHECK-DAG: DBG_VALUE 30, $noreg, ![[T0_VAR2]]
+  ; CHECK-NOT: DBG_VALUE {{[0-9]+}}, $noreg, ![[T0_VAR1]]
+  ; CHECK-NOT: DBG_VALUE {{[0-9]+}}, $noreg, ![[T0_VAR3]]
+  bb.3:
+  ; predecessors: %bb.1, %bb.2
+    RETURN implicit-def dead $arguments
+...
+
+---
+# var0: Its debug value is set once in bb.0 and valid throughout the function.
+#       So a new DBG_VALUE will be added to the beginnings of all other BBs
+#       (bb.1, bb.2, and bb.3).
+# var1: Its debug value is set in bb.0, but is reset to no info back later in
+#       bb.0. So no DBG_VALUEs will be added in other BBs.
+# var2: Its debug value is set both in bb.1 and bb.2 with the same value (The
+#       same kind (local) and same local index). bb.3 will have a new DBG_VALUE
+#       representing that value.
+# var3: Its debug value is set both in bb.1 and bb.2 but with 
diff erent values.
+#       Both are locals, but their indices are 
diff erent. bb.3 will NOT have a
+#       new DBG_VALUE instruction because its predecessors don't agree on a
+#       value.
+# var4: Its debug value is set both in bb.1 and bb.2 but with 
diff erent values.
+#       They have 
diff erent kinds; one is a local and the other is a stack
+#       operand. (Their index is the same, but it doesn't matter.) bb.3 will NOT
+#       have a new DBG_VALUE instruction because its predecessors don't agree on
+#       a value.
+# CHECK-LABEL: name: test_target_indices
+name: test_target_indices
+liveins:
+  - { reg: '$arguments' }
+body: |
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $arguments
+    DBG_VALUE target-index(wasm-local), $noreg, !15, !DIExpression(), debug-location !16
+    DBG_VALUE target-index(wasm-operand-stack) + 2, $noreg, !17, !DIExpression(), debug-location !16
+    %0:i32 = CONST_I32 1, implicit-def $arguments
+    DBG_VALUE $noreg, $noreg, !17, !DIExpression(), debug-location !16
+    BR_IF %bb.2, %0:i32, implicit-def $arguments
+
+  ; CHECK: bb.1:
+  ; CHECK: DBG_VALUE target-index(wasm-local), $noreg, ![[T1_VAR0]]
+  bb.1:
+  ; predecessors: %bb.0
+    successors: %bb.3
+    DBG_VALUE target-index(wasm-local) + 2, $noreg, !18, !DIExpression(), debug-location !16
+    DBG_VALUE target-index(wasm-local) + 3, $noreg, !19, !DIExpression(), debug-location !16
+    DBG_VALUE target-index(wasm-operand-stack) + 3, $noreg, !20, !DIExpression(), debug-location !16
+    BR %bb.3, implicit-def $arguments
+
+  ; CHECK: bb.2:
+  ; CHECK: DBG_VALUE target-index(wasm-local), $noreg, ![[T1_VAR0]]
+  bb.2:
+  ; predecessors: %bb.0
+    successors: %bb.3
+    DBG_VALUE target-index(wasm-local) + 2, $noreg, !18, !DIExpression(), debug-location !16
+    DBG_VALUE target-index(wasm-local) + 5, $noreg, !19, !DIExpression(), debug-location !16
+    DBG_VALUE target-index(wasm-local) + 3, $noreg, !20, !DIExpression(), debug-location !16
+    BR %bb.3, implicit-def $arguments
+
+  ; CHECK: bb.3:
+  ; CHECK-DAG: DBG_VALUE target-index(wasm-local), $noreg, ![[T1_VAR0]]
+  ; CHECK-DAG: DBG_VALUE target-index(wasm-local) + 2, $noreg, ![[T1_VAR2]]
+  ; CHECK-NOT: DBG_VALUE target-index(wasm-local){{.*}}, $noreg, ![[T1_VAR3]]
+  ; CHECK-NOT: DBG_VALUE target-index(wasm-local){{.*}}, $noreg, ![[T1_VAR4]]
+  bb.3:
+  ; predecessors: %bb.1, %bb.2
+    RETURN implicit-def dead $arguments
+...


        


More information about the llvm-commits mailing list