[llvm] a971bc3 - Move DBG_VALUE's that depend on loads to after a

Shubham Sandeep Rastogi via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 16:11:15 PDT 2023


Author: Shubham Sandeep Rastogi
Date: 2023-04-24T16:10:54-07:00
New Revision: a971bc38cee892fb490b806eec74f2188fb70416

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

LOG: Move DBG_VALUE's that depend on loads to after a
load if the load is moved due to the pre register allocation ld/st
optimization pass

The issue here is that there can be a scenario where debug information
is lost because of the pre register allocation load store optimization
pass, where a load who's result describes the debug infomation for a
local variable gets moved below the load and that causes the debug
information for that load to get lost.

Example:

Before the Pre Register Allocation Load Store Pass
inst_a
%2 = ld ...
inst_b
DBG_VALUE %2, "x", ...
%3 = ld ...

After the Pass:
inst_a
inst_b
DBG_VALUE %2, "x", ...
%2 = ld ...
%3 = ld ...

The load has now been moved to after the DBG_VAL that uses its result
and the debug info for "x" has been lost. What we want is:

inst_a
inst_b
%2 = ld ...
DBG_VALUE %2, "x", ...
%3 = ld ...

Which is what this patch addresses

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

Added: 
    llvm/test/DebugInfo/ARM/move-dbg-value-after-value-list.mir
    llvm/test/DebugInfo/ARM/move-dbg-value-lists.mir
    llvm/test/DebugInfo/ARM/move-dbg-value-same-reg.mir
    llvm/test/DebugInfo/ARM/move-dbg-values-imm-test.mir
    llvm/test/DebugInfo/ARM/move-dbg-values.mir

Modified: 
    llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index 0a38f5633ae3b..fd24f2abd57de 100644
--- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -2172,10 +2172,10 @@ namespace {
                           unsigned &NewOpc, Register &EvenReg, Register &OddReg,
                           Register &BaseReg, int &Offset, Register &PredReg,
                           ARMCC::CondCodes &Pred, bool &isT2);
-    bool RescheduleOps(MachineBasicBlock *MBB,
-                       SmallVectorImpl<MachineInstr *> &Ops,
-                       unsigned Base, bool isLd,
-                       DenseMap<MachineInstr*, unsigned> &MI2LocMap);
+    bool RescheduleOps(
+        MachineBasicBlock *MBB, SmallVectorImpl<MachineInstr *> &Ops,
+        unsigned Base, bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
+        SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap);
     bool RescheduleLoadStoreInstrs(MachineBasicBlock *MBB);
     bool DistributeIncrements();
     bool DistributeIncrements(Register Base);
@@ -2324,10 +2324,10 @@ bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(
   return true;
 }
 
-bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
-                                 SmallVectorImpl<MachineInstr *> &Ops,
-                                 unsigned Base, bool isLd,
-                                 DenseMap<MachineInstr*, unsigned> &MI2LocMap) {
+bool ARMPreAllocLoadStoreOpt::RescheduleOps(
+    MachineBasicBlock *MBB, SmallVectorImpl<MachineInstr *> &Ops, unsigned Base,
+    bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
+    SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap) {
   bool RetVal = false;
 
   // Sort by offset (in reverse order).
@@ -2476,6 +2476,12 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
         } else {
           for (unsigned i = 0; i != NumMove; ++i) {
             MachineInstr *Op = Ops.pop_back_val();
+            if (isLd) {
+              // Populate RegisterMap with all Registers defined by loads.
+              Register Reg = Op->getOperand(0).getReg();
+              RegisterMap[Reg];
+            }
+
             MBB->splice(InsertPos, MBB, Op);
           }
         }
@@ -2489,6 +2495,44 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
   return RetVal;
 }
 
+static void forEachDbgRegOperand(MachineInstr *MI,
+                                 std::function<void(MachineOperand &)> Fn) {
+  if (MI->isNonListDebugValue()) {
+    auto &Op = MI->getOperand(0);
+    if (Op.isReg())
+      Fn(Op);
+  } else {
+    for (unsigned I = 2; I < MI->getNumOperands(); I++) {
+      auto &Op = MI->getOperand(I);
+      if (Op.isReg())
+        Fn(Op);
+    }
+  }
+}
+
+// Update the RegisterMap with the instruction that was moved because a
+// DBG_VALUE_LIST may need to be moved again.
+static void updateRegisterMapForDbgValueListAfterMove(
+    SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap,
+    MachineInstr *DbgValueListInstr, MachineInstr *InstrToReplace) {
+
+  forEachDbgRegOperand(DbgValueListInstr, [&](MachineOperand &Op) {
+    auto RegIt = RegisterMap.find(Op.getReg());
+    if (RegIt == RegisterMap.end())
+      return;
+    auto &InstrVec = RegIt->getSecond();
+    for (unsigned I = 0; I < InstrVec.size(); I++)
+      if (InstrVec[I] == InstrToReplace)
+        InstrVec[I] = DbgValueListInstr;
+  });
+}
+
+static DebugVariable createDebugVariableFromMachineInstr(MachineInstr *MI) {
+  auto DbgVar = DebugVariable(MI->getDebugVariable(), MI->getDebugExpression(),
+                              MI->getDebugLoc()->getInlinedAt());
+  return DbgVar;
+}
+
 bool
 ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
   bool RetVal = false;
@@ -2501,6 +2545,10 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
   Base2InstMap Base2StsMap;
   BaseVec LdBases;
   BaseVec StBases;
+  // This map is used to track the relationship between the virtual
+  // register that is the result of a load that is moved and the DBG_VALUE
+  // MachineInstr pointer that uses that virtual register.
+  SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> RegisterMap;
 
   unsigned Loc = 0;
   MachineBasicBlock::iterator MBBI = MBB->begin();
@@ -2563,7 +2611,7 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
       unsigned Base = LdBases[i];
       SmallVectorImpl<MachineInstr *> &Lds = Base2LdsMap[Base];
       if (Lds.size() > 1)
-        RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap);
+        RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap, RegisterMap);
     }
 
     // Re-schedule stores.
@@ -2571,7 +2619,7 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
       unsigned Base = StBases[i];
       SmallVectorImpl<MachineInstr *> &Sts = Base2StsMap[Base];
       if (Sts.size() > 1)
-        RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap);
+        RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap, RegisterMap);
     }
 
     if (MBBI != E) {
@@ -2582,6 +2630,257 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
     }
   }
 
+  // Reschedule DBG_VALUEs to match any loads that were moved. When a load is
+  // sunk beyond a DBG_VALUE that is referring to it, the DBG_VALUE becomes a
+  // use-before-def, resulting in a loss of debug info.
+
+  // Example:
+  // Before the Pre Register Allocation Load Store Pass
+  // inst_a
+  // %2 = ld ...
+  // inst_b
+  // DBG_VALUE %2, "x", ...
+  // %3 = ld ...
+
+  // After the Pass:
+  // inst_a
+  // inst_b
+  // DBG_VALUE %2, "x", ...
+  // %2 = ld ...
+  // %3 = ld ...
+
+  // The code below addresses this by moving the DBG_VALUE to the position
+  // immediately after the load.
+
+  // Example:
+  // After the code below:
+  // inst_a
+  // inst_b
+  // %2 = ld ...
+  // DBG_VALUE %2, "x", ...
+  // %3 = ld ...
+
+  // The algorithm works in two phases: First RescheduleOps() populates the
+  // RegisterMap with registers that were moved as keys, there is no value
+  // inserted. In the next phase, every MachineInstr in a basic block is
+  // iterated over. If it is a valid DBG_VALUE or DBG_VALUE_LIST and it uses one
+  // or more registers in the RegisterMap, the RegisterMap and InstrMap are
+  // populated with the MachineInstr. If the DBG_VALUE or DBG_VALUE_LIST
+  // describes debug information for a variable that already exists in the
+  // DbgValueSinkCandidates, the MachineInstr in the DbgValueSinkCandidates must
+  // be set to undef. If the current MachineInstr is a load that was moved,
+  // undef the corresponding DBG_VALUE or DBG_VALUE_LIST and clone it to below
+  // the load.
+
+  // To illustrate the above algorithm visually let's take this example.
+
+  // Before the Pre Register Allocation Load Store Pass:
+  // %2 = ld ...
+  // DBG_VALUE %2, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // %3 = ld ...
+  // DBG_VALUE %3, A, ..., # Z
+  // %4 = ld ...
+
+  // After Pre Register Allocation Load Store Pass:
+  // DBG_VALUE %2, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE %3, A, ..., # Z
+  // %2 = ld ...
+  // %3 = ld ...
+  // %4 = ld ...
+
+  // The algorithm below does the following:
+
+  // In the beginning, the RegisterMap will have been populated with the virtual
+  // registers %2, and %3, the DbgValueSinkCandidates and the InstrMap will be
+  // empty. DbgValueSinkCandidates = {}, RegisterMap = {2 -> {}, 3 -> {}},
+  // InstrMap {}
+  // -> DBG_VALUE %2, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE %3, A, ..., # Z
+  // %2 = ld ...
+  // %3 = ld ...
+  // %4 = ld ...
+
+  // After the first DBG_VALUE (denoted with an X) is processed, the
+  // DbgValueSinkCandidates and InstrMap will be populated and the RegisterMap
+  // entry for %2 will be populated as well. DbgValueSinkCandidates = {A -> X},
+  // RegisterMap = {2 -> {X}, 3 -> {}}, InstrMap {X -> 2}
+  // DBG_VALUE %2, A, .... # X
+  // -> DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE %3, A, ..., # Z
+  // %2 = ld ...
+  // %3 = ld ...
+  // %4 = ld ...
+
+  // After the DBG_VALUE Y is processed, the DbgValueSinkCandidates is updated
+  // to now hold Y for A and the RegisterMap is also updated to remove X from
+  // %2, this is because both X and Y describe the same debug variable A. X is
+  // also updated to have a $noreg as the first operand.
+  // DbgValueSinkCandidates = {A -> {Y}}, RegisterMap = {2 -> {}, 3 -> {}},
+  // InstrMap = {X-> 2}
+  // DBG_VALUE $noreg, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // -> DBG_VALUE %3, A, ..., # Z
+  // %2 = ld ...
+  // %3 = ld ...
+  // %4 = ld ...
+
+  // After DBG_VALUE Z is processed, the DbgValueSinkCandidates is updated to
+  // hold Z fr A, the RegisterMap is updated to hold Z for %3, and the InstrMap
+  // is updated to have Z mapped to %3. This is again because Z describes the
+  // debug variable A, Y is not updated to have $noreg as first operand because
+  // its first operand is an immediate, not a register.
+  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
+  // InstrMap = {X -> 2, Z -> 3}
+  // DBG_VALUE $noreg, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE %3, A, ..., # Z
+  // -> %2 = ld ...
+  // %3 = ld ...
+  // %4 = ld ...
+
+  // Nothing happens here since the RegisterMap for %2 contains no value.
+  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
+  // InstrMap = {X -> 2, Z -> 3}
+  // DBG_VALUE $noreg, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE %3, A, ..., # Z
+  // %2 = ld ...
+  // -> %3 = ld ...
+  // %4 = ld ...
+
+  // Since the RegisterMap contains Z as a value for %3, the MachineInstr
+  // pointer Z is copied to come after the load for %3 and the old Z's first
+  // operand is changed to $noreg the Basic Block iterator is moved to after the
+  // DBG_VALUE Z's new position.
+  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
+  // InstrMap = {X -> 2, Z -> 3}
+  // DBG_VALUE $noreg, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE $noreg, A, ..., # Old Z
+  // %2 = ld ...
+  // %3 = ld ...
+  // DBG_VALUE %3, A, ..., # Z
+  // -> %4 = ld ...
+
+  // Nothing happens for %4 and the algorithm exits having processed the entire
+  // Basic Block.
+  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
+  // InstrMap = {X -> 2, Z -> 3}
+  // DBG_VALUE $noreg, A, .... # X
+  // DBG_VALUE 0, A, ... # Y
+  // DBG_VALUE $noreg, A, ..., # Old Z
+  // %2 = ld ...
+  // %3 = ld ...
+  // DBG_VALUE %3, A, ..., # Z
+  // %4 = ld ...
+
+  // This map is used to track the relationship between
+  // a Debug Variable and the DBG_VALUE MachineInstr pointer that describes the
+  // debug information for that Debug Variable.
+  SmallDenseMap<DebugVariable, MachineInstr *, 8> DbgValueSinkCandidates;
+  // This map is used to track the relationship between a DBG_VALUE or
+  // DBG_VALUE_LIST MachineInstr pointer and Registers that it uses.
+  SmallDenseMap<MachineInstr *, SmallVector<Register>, 8> InstrMap;
+  for (MBBI = MBB->begin(), E = MBB->end(); MBBI != E; ++MBBI) {
+    MachineInstr &MI = *MBBI;
+
+    auto PopulateRegisterAndInstrMapForDebugInstr = [&](Register Reg) {
+      auto RegIt = RegisterMap.find(Reg);
+      if (RegIt == RegisterMap.end())
+        return;
+      auto &InstrVec = RegIt->getSecond();
+      InstrVec.push_back(&MI);
+      InstrMap[&MI].push_back(Reg);
+    };
+
+    if (MI.isDebugValue()) {
+      auto *DILocalVar = MI.getDebugVariable();
+      // TODO: This should not happen, have to fix the MIR verifier to check for
+      // such instances and fix them.
+      if (!DILocalVar)
+        continue;
+      auto DbgVar = createDebugVariableFromMachineInstr(&MI);
+      // If the first operand is a register and it exists in the RegisterMap, we
+      // know this is a DBG_VALUE that uses the result of a load that was moved,
+      // and is therefore a candidate to also be moved, add it to the
+      // RegisterMap and InstrMap.
+      forEachDbgRegOperand(&MI, [&](MachineOperand &Op) {
+        PopulateRegisterAndInstrMapForDebugInstr(Op.getReg());
+      });
+
+      // If the current DBG_VALUE describes the same variable as one of the
+      // in-flight DBG_VALUEs, remove the candidate from the list and set it to
+      // undef. Moving one DBG_VALUE past another would result in the variable's
+      // value going back in time when stepping through the block in the
+      // debugger.
+      auto InstrIt = DbgValueSinkCandidates.find(DbgVar);
+      if (InstrIt != DbgValueSinkCandidates.end()) {
+        auto *Instr = InstrIt->getSecond();
+        auto RegIt = InstrMap.find(Instr);
+        if (RegIt != InstrMap.end()) {
+          const auto &RegVec = RegIt->getSecond();
+          // For every Register in the RegVec, remove the MachineInstr in the
+          // RegisterMap that describes the DbgVar.
+          for (auto &Reg : RegVec) {
+            auto RegIt = RegisterMap.find(Reg);
+            if (RegIt == RegisterMap.end())
+              continue;
+            auto &InstrVec = RegIt->getSecond();
+            auto IsDbgVar = [&](MachineInstr *I) -> bool {
+              auto Var = createDebugVariableFromMachineInstr(I);
+              return Var == DbgVar;
+            };
+
+            InstrVec.erase(
+                std::remove_if(InstrVec.begin(), InstrVec.end(), IsDbgVar),
+                InstrVec.end());
+          }
+          forEachDbgRegOperand(Instr,
+                               [&](MachineOperand &Op) { Op.setReg(0); });
+        }
+      }
+      DbgValueSinkCandidates[DbgVar] = &MI;
+    } else {
+      // If the first operand of a load matches with a DBG_VALUE in RegisterMap,
+      // then move that DBG_VALUE to below the load.
+      auto Opc = MI.getOpcode();
+      if (!isLoadSingle(Opc))
+        continue;
+      auto Reg = MI.getOperand(0).getReg();
+      auto RegIt = RegisterMap.find(Reg);
+      if (RegIt == RegisterMap.end())
+        continue;
+      auto &DbgInstrVec = RegIt->getSecond();
+      if (!DbgInstrVec.size())
+        continue;
+      for (auto *DbgInstr : DbgInstrVec) {
+        MachineBasicBlock::iterator InsertPos = std::next(MBBI);
+        auto *ClonedMI = MI.getMF()->CloneMachineInstr(DbgInstr);
+        MBB->insert(InsertPos, ClonedMI);
+        MBBI++;
+        //  Erase the entry into the DbgValueSinkCandidates for the DBG_VALUE
+        //  that was moved.
+        auto DbgVar = createDebugVariableFromMachineInstr(DbgInstr);
+        auto DbgIt = DbgValueSinkCandidates.find(DbgVar);
+        // If the instruction is a DBG_VALUE_LIST, it may have already been
+        // erased from the DbgValueSinkCandidates. Only erase if it exists in
+        // the DbgValueSinkCandidates.
+        if (DbgIt != DbgValueSinkCandidates.end())
+          DbgValueSinkCandidates.erase(DbgIt);
+        // Zero out original dbg instr
+        forEachDbgRegOperand(DbgInstr,
+                             [&](MachineOperand &Op) { Op.setReg(0); });
+        // Update RegisterMap with ClonedMI because it might have to be moved
+        // again.
+        if (DbgInstr->isDebugValueList())
+          updateRegisterMapForDbgValueListAfterMove(RegisterMap, ClonedMI,
+                                                    DbgInstr);
+      }
+    }
+  }
   return RetVal;
 }
 

diff  --git a/llvm/test/DebugInfo/ARM/move-dbg-value-after-value-list.mir b/llvm/test/DebugInfo/ARM/move-dbg-value-after-value-list.mir
new file mode 100644
index 0000000000000..23e43ccb046d7
--- /dev/null
+++ b/llvm/test/DebugInfo/ARM/move-dbg-value-after-value-list.mir
@@ -0,0 +1,66 @@
+# RUN: llc %s -start-after=arm-mve-vpt-opts -stop-after=arm-prera-ldst-opt -o - | FileCheck %s
+# CHECK: %5:rgpr = t2MOVCCr %3, killed %4, 0 /* CC::eq */, $cpsr, debug-location !14
+# CHECK-NEXT: DBG_VALUE 0, $noreg, !10, !DIExpression(), debug-location !14
+# CHECK-NEXT: DBG_VALUE 1, $noreg, !10, !DIExpression(), debug-location !14
+# CHECK-NEXT: DBG_VALUE_LIST !10, !DIExpression(), $noreg, $noreg, debug-location !14
+# CHECK-NEXT: DBG_VALUE $noreg, $noreg, !10, !DIExpression(), debug-location !14
+# CHECK-NEXT: %0:rgpr = t2LDRi12 %5, 0, 14 /* CC::al */, $noreg, debug-location !14 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+# CHECK-NEXT: %6:rgpr = t2LDRi12 %5, 4, 14 /* CC::al */, $noreg, debug-location !14 :: (load (s32) from %ir.btc_user_copy)
+# CHECK-NEXT: %2:gpr = t2LDRi12 %5, 8, 14 /* CC::al */, $noreg, debug-location !14 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+# CHECK-NEXT: DBG_VALUE %2, $noreg, !10, !DIExpression(), debug-location !14
+# CHECK-NEXT: %7:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+# CHECK-NEXT: %8:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+# CHECK-NEXT: %9:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+# CHECK-NEXT: %10:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+
+# This test specifically checks if a DBG_VALUE_LIST that is succeeded by a DBG_VALUE can be properly undefed and the DBG_VALUE is the one that is moved. Assuming both instructions describe the same local variable. 
+
+--- |
+  target triple = "thumbv7k-apple-watchos8.0.0"
+  %struct.backtrace_control = type {}
+  @backtrace_user.ctl_default = internal unnamed_addr constant %struct.backtrace_control zeroinitializer, !dbg !0
+  define i32 @backtrace_user(ptr nocapture noundef writeonly %bt, i32 noundef %max_frames, ptr noundef readonly %ctl_in, ptr nocapture noundef readnone %info_out) local_unnamed_addr #0 !dbg !2 {entry:
+    %tobool.not = icmp eq ptr %ctl_in, null, !dbg !95
+    %.backtrace_user.ctl_default = select i1 %tobool.not, ptr @backtrace_user.ctl_default, ptr %ctl_in, !dbg !95
+    %btc_user_copy = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    %btc_user_copy_context = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    ret i32 undef, !dbg !95
+  }
+  !llvm.module.flags = !{!88, !93}
+  !llvm.dbg.cu = !{!32}
+  !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+  !1 = distinct !DIGlobalVariable(type: !11, isDefinition: true)
+  !2 = distinct !DISubprogram(unit: !32, retainedNodes: !38)
+  !3 = !DIFile(filename: "backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !11 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !12)
+  !12 = distinct !DICompositeType(tag: DW_TAG_member, offset: 32)
+  !32 = distinct !DICompileUnit(language: DW_LANG_C11, file: !33, sdk: "MacOSX13.0.sdk")
+  !33 = !DIFile(filename: "/Users/shubham/Development/Delta/backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !38 = !{!60, !85}
+  !60 = !DILocalVariable(scope: !2, type: !62)
+  !62 = distinct !DICompositeType(tag: DW_TAG_union_type, size: 128)
+  !85 = !DILabel(scope: !2, name: "out", file: !3, line: 102)
+  !88 = !{i32 2, !"Debug Info Version", i32 3}
+  !93 = !{i32 7, !"frame-pointer", i32 1}
+  !95 = !DILocation(line: 5, column: 10, scope: !2)
+name:            backtrace_user
+registers:
+  - {id: 0, class: rgpr, }
+  - {id: 1, class: gpr, }
+  - {id: 2, class: gpr, }
+body:             |
+  bb.0.entry:
+    %10:rgpr = COPY $r2
+    %13:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @backtrace_user.ctl_default, debug-location !95
+    %15:rgpr = t2MOVCCr %10, killed %13, 0 /* CC::eq */, $cpsr, debug-location !95
+    DBG_VALUE 0, $noreg, !60, !DIExpression(), debug-location !95
+    %0:rgpr = t2LDRi12 %15, 0, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+    DBG_VALUE 1, $noreg, !60, !DIExpression(), debug-location !95
+    %16:rgpr = t2LDRi12 %15, 4, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy)
+    DBG_VALUE_LIST !60, !DIExpression(), %16, %0, debug-location !95
+    %2:gpr = t2LDRi12 %15, 8, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+    DBG_VALUE %2, $noreg, !60, !DIExpression(), debug-location !95
+    %31:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr
+    %32:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr
+    %33:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr
+    %34:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr

diff  --git a/llvm/test/DebugInfo/ARM/move-dbg-value-lists.mir b/llvm/test/DebugInfo/ARM/move-dbg-value-lists.mir
new file mode 100644
index 0000000000000..681d89b03936d
--- /dev/null
+++ b/llvm/test/DebugInfo/ARM/move-dbg-value-lists.mir
@@ -0,0 +1,58 @@
+# RUN: llc %s -start-after=arm-mve-vpt-opts -stop-after=arm-prera-ldst-opt -o - | FileCheck %s
+# CHECK: %5:rgpr = t2MOVCCr %3, killed %4, 0 /* CC::eq */, $cpsr, debug-location !14
+# CHECK-NEXT: DBG_VALUE 0, $noreg, !10, !DIExpression(), debug-location !14
+# CHECK-NEXT: DBG_VALUE 1, $noreg, !10, !DIExpression(), debug-location !14
+# CHECK-NEXT: DBG_VALUE_LIST !10, !DIExpression(), $noreg, $noreg, debug-location !14
+# CHECK-NEXT: %0:rgpr = t2LDRi12 %5, 0, 14 /* CC::al */, $noreg, debug-location !14 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+# CHECK-NEXT: DBG_VALUE_LIST !10, !DIExpression(), $noreg, $noreg, debug-location !14
+# CHECK-NEXT: %6:rgpr = t2LDRi12 %5, 4, 14 /* CC::al */, $noreg, debug-location !14 :: (load (s32) from %ir.btc_user_copy)
+# CHECK-NEXT: DBG_VALUE_LIST !10, !DIExpression(), %6, %0, debug-location !14
+# CHECK-NEXT: %2:gpr = t2LDRi12 %5, 8, 14 /* CC::al */, $noreg, debug-location !14 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+# CHECK-NEXT: %7:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+# CHECK-NEXT: DBG_VALUE %2, $noreg, !10, !DIExpression(), debug-location !14
+--- |
+  target triple = "thumbv7k-apple-watchos8.0.0"
+  %struct.backtrace_control = type {}
+  @backtrace_user.ctl_default = internal unnamed_addr constant %struct.backtrace_control zeroinitializer, !dbg !0
+  define i32 @backtrace_user(ptr nocapture noundef writeonly %bt, i32 noundef %max_frames, ptr noundef readonly %ctl_in, ptr nocapture noundef readnone %info_out) local_unnamed_addr #0 !dbg !2 {entry:
+    %tobool.not = icmp eq ptr %ctl_in, null, !dbg !95
+    %.backtrace_user.ctl_default = select i1 %tobool.not, ptr @backtrace_user.ctl_default, ptr %ctl_in, !dbg !95
+    %btc_user_copy = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    %btc_user_copy_context = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    ret i32 undef, !dbg !95
+  }
+  !llvm.module.flags = !{!88, !93}
+  !llvm.dbg.cu = !{!32}
+  !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+  !1 = distinct !DIGlobalVariable(type: !11, isDefinition: true)
+  !2 = distinct !DISubprogram(unit: !32, retainedNodes: !38)
+  !3 = !DIFile(filename: "backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !11 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !12)
+  !12 = distinct !DICompositeType(tag: DW_TAG_member, offset: 32)
+  !32 = distinct !DICompileUnit(language: DW_LANG_C11, file: !33, sdk: "MacOSX13.0.sdk")
+  !33 = !DIFile(filename: "/Users/shubham/Development/Delta/backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !38 = !{!60, !85}
+  !60 = !DILocalVariable(scope: !2, type: !62)
+  !62 = distinct !DICompositeType(tag: DW_TAG_union_type, size: 64)
+  !85 = !DILabel(scope: !2, name: "out", file: !3, line: 102)
+  !88 = !{i32 2, !"Debug Info Version", i32 3}
+  !93 = !{i32 7, !"frame-pointer", i32 1}
+  !95 = !DILocation(line: 5, column: 10, scope: !2)
+name:            backtrace_user
+registers:
+  - {id: 0, class: rgpr, }
+  - {id: 1, class: gpr, }
+  - {id: 2, class: gpr, }
+body:             |
+  bb.0.entry:
+    %10:rgpr = COPY $r2
+    %13:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @backtrace_user.ctl_default, debug-location !95
+    %15:rgpr = t2MOVCCr %10, killed %13, 0 /* CC::eq */, $cpsr, debug-location !95
+    DBG_VALUE 0, $noreg, !60, !DIExpression(), debug-location !95
+    %0:rgpr = t2LDRi12 %15, 0, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+    DBG_VALUE 1, $noreg, !60, !DIExpression(), debug-location !95
+    %16:rgpr = t2LDRi12 %15, 4, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy)
+    DBG_VALUE_LIST !60, !DIExpression(), %16, %0, debug-location !95
+    %2:gpr = t2LDRi12 %15, 8, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+    %31:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr
+    DBG_VALUE %2, $noreg, !60, !DIExpression(), debug-location !95

diff  --git a/llvm/test/DebugInfo/ARM/move-dbg-value-same-reg.mir b/llvm/test/DebugInfo/ARM/move-dbg-value-same-reg.mir
new file mode 100644
index 0000000000000..7a5749d8a2495
--- /dev/null
+++ b/llvm/test/DebugInfo/ARM/move-dbg-value-same-reg.mir
@@ -0,0 +1,64 @@
+# RUN: llc %s -start-after=arm-mve-vpt-opts -stop-after=arm-prera-ldst-opt -o - | FileCheck %s
+# CHECK: %5:rgpr = t2MOVCCr %3, killed %4, 0 /* CC::eq */, $cpsr, debug-location !{{[0-9]+}}
+# CHECK-NEXT: DBG_VALUE 0, $noreg, ![[DBG:[0-9]+]], !DIExpression(), debug-location !{{[0-9]+}}
+# CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[DBG]], !DIExpression(), debug-location !{{[0-9]+}}
+# CHECK-NEXT: DBG_VALUE $noreg, $noreg, !{{[0-9]+}}, !DIExpression(), debug-location !{{[0-9]+}}
+# CHECK-NEXT: %0:rgpr = t2LDRi12 %5, 0, 14 /* CC::al */, $noreg, debug-location !{{[0-9]+}} :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+# CHECK-NEXT: DBG_VALUE %0, $noreg, ![[DBG]], !DIExpression(), debug-location !{{[0-9]+}}
+# CHECK-NEXT: DBG_VALUE %0, $noreg, !{{[0-9]+}}, !DIExpression(), debug-location !{{[0-9]+}}
+# CHECK-NEXT: %6:rgpr = t2LDRi12 %5, 4, 14 /* CC::al */, $noreg, debug-location !{{[0-9]+}} :: (load (s32) from %ir.btc_user_copy)
+# CHECK-NEXT: %2:gpr = t2LDRi12 %5, 8, 14 /* CC::al */, $noreg, debug-location !{{[0-9]+}} :: (load (s32) from %ir.btc_user_copy_context, align 8)
+# CHECK-NEXT: %7:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+# CHECK-NEXT: DBG_VALUE %2, $noreg, ![[DBG]], !DIExpression(), debug-location !{{[0-9]+}}
+
+# This test checks the case where two DBG_VALUEs share the same virtual register but describe 
diff erent local variables.
+
+--- |
+  target triple = "thumbv7k-apple-watchos8.0.0"
+  %struct.backtrace_control = type {}
+  @backtrace_user.ctl_default = internal unnamed_addr constant %struct.backtrace_control zeroinitializer, !dbg !0
+  define i32 @backtrace_user(ptr nocapture noundef writeonly %bt, i32 noundef %max_frames, ptr noundef readonly %ctl_in, ptr nocapture noundef readnone %info_out) local_unnamed_addr #0 !dbg !2 {entry:
+    %tobool.not = icmp eq ptr %ctl_in, null, !dbg !95
+    %.backtrace_user.ctl_default = select i1 %tobool.not, ptr @backtrace_user.ctl_default, ptr %ctl_in, !dbg !95
+    %btc_user_copy = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    %btc_user_copy_context = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    ret i32 undef, !dbg !95
+  }
+  !llvm.module.flags = !{!88, !93}
+  !llvm.dbg.cu = !{!32}
+  !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+  !1 = distinct !DIGlobalVariable(type: !11, isDefinition: true)
+  !2 = distinct !DISubprogram(unit: !32, retainedNodes: !38)
+  !3 = !DIFile(filename: "backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !11 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !12)
+  !12 = distinct !DICompositeType(tag: DW_TAG_member, offset: 32)
+  !16 = !DIDerivedType(tag: DW_TAG_typedef, baseType: !21)
+  !21 = !DIBasicType()
+  !32 = distinct !DICompileUnit(language: DW_LANG_C11, file: !33, sdk: "MacOSX13.0.sdk")
+  !33 = !DIFile(filename: "/Users/shubham/Development/Delta/backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !38 = !{!59, !60, !85}
+  !59 = !DILocalVariable(scope: !2, type: !16)
+  !60 = !DILocalVariable(scope: !2, type: !62)
+  !62 = distinct !DICompositeType(tag: DW_TAG_union_type, size: 128)
+  !85 = !DILabel(scope: !2, name: "out", file: !3, line: 102)
+  !88 = !{i32 2, !"Debug Info Version", i32 3}
+  !93 = !{i32 7, !"frame-pointer", i32 1}
+  !95 = !DILocation(line: 5, column: 10, scope: !2)
+name:            backtrace_user
+registers:
+  - {id: 0, class: rgpr, }
+  - {id: 1, class: gpr, }
+  - {id: 2, class: gpr, }
+body:             |
+  bb.0.entry:
+    %10:rgpr = COPY $r2
+    %13:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @backtrace_user.ctl_default, debug-location !95
+    %15:rgpr = t2MOVCCr %10, killed %13, 0 /* CC::eq */, $cpsr, debug-location !95
+    DBG_VALUE 0, $noreg, !60, !DIExpression(), debug-location !95
+    %0:rgpr = t2LDRi12 %15, 0, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+    DBG_VALUE %0, $noreg, !60, !DIExpression(), debug-location !95
+    DBG_VALUE %0, $noreg, !59, !DIExpression(), debug-location !95
+    %16:rgpr = t2LDRi12 %15, 4, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy)
+    %2:gpr = t2LDRi12 %15, 8, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+    %31:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr
+    DBG_VALUE %2, $noreg, !60, !DIExpression(), debug-location !95

diff  --git a/llvm/test/DebugInfo/ARM/move-dbg-values-imm-test.mir b/llvm/test/DebugInfo/ARM/move-dbg-values-imm-test.mir
new file mode 100644
index 0000000000000..5992eb596089a
--- /dev/null
+++ b/llvm/test/DebugInfo/ARM/move-dbg-values-imm-test.mir
@@ -0,0 +1,130 @@
+# RUN: llc -O2 %s -start-after=arm-mve-vpt-opts -stop-after=arm-prera-ldst-opt -o -  | FileCheck %s
+# CHECK: DBG_VALUE 13, $noreg, !11, !DIExpression(), debug-location !13
+
+
+# This test checks to make sure that a DBG_VALUE that uses an immediate doesn't get zero-ed out by a DBG_VALUE that comes later in the basic block, and describes the same variable.
+
+--- |
+  ; ModuleID = '/Users/shubham/Development/llvm-project/llvm/test/DebugInfo/Generic/incorrect-variable-debugloc1.ll'
+  source_filename = "/Users/shubham/Development/llvm-project/llvm/test/DebugInfo/Generic/incorrect-variable-debugloc1.ll"
+  target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+  target triple = "armv8-unknown-linux"
+  
+  ; Function Attrs: uwtable
+  define i32 @main() #0 !dbg !6 {
+  entry:
+    %c = alloca i32, align 4
+    tail call void @llvm.dbg.value(metadata i32 13, metadata !11, metadata !DIExpression()), !dbg !13
+    store volatile i32 13, ptr %c, align 4, !dbg !14
+    %call = tail call i32 @_Z4funcv(), !dbg !15
+    tail call void @llvm.dbg.value(metadata i32 %call, metadata !11, metadata !DIExpression()), !dbg !13
+    store volatile i32 %call, ptr %c, align 4, !dbg !15
+    tail call void @llvm.dbg.value(metadata ptr %c, metadata !11, metadata !DIExpression(DW_OP_deref)), !dbg !13
+    %c.0.c.0. = load volatile i32, ptr %c, align 4, !dbg !16
+    ret i32 %c.0.c.0., !dbg !16
+  }
+  
+  declare i32 @_Z4funcv() #1
+  
+  ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+  declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+  
+  attributes #0 = { uwtable "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+  attributes #1 = { "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+  attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4}
+  !llvm.ident = !{!5}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.6.0 (trunk 223522)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+  !1 = !DIFile(filename: "test.cpp", directory: "/home/kromanova/ngh/ToT_latest/llvm/test/DebugInfo")
+  !2 = !{}
+  !3 = !{i32 2, !"Dwarf Version", i32 2}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{!"clang version 3.6.0 (trunk 223522)"}
+  !6 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !7, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
+  !7 = !DISubroutineType(types: !8)
+  !8 = !{!9}
+  !9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+  !10 = !{!11}
+  !11 = !DILocalVariable(name: "c", scope: !6, file: !1, line: 5, type: !12)
+  !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !9)
+  !13 = !DILocation(line: 5, column: 16, scope: !6)
+  !14 = !DILocation(line: 5, column: 3, scope: !6)
+  !15 = !DILocation(line: 6, column: 7, scope: !6)
+  !16 = !DILocation(line: 7, column: 3, scope: !6)
+
+...
+---
+name:            main
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+failedISel:      false
+tracksRegLiveness: true
+hasWinCFI:       false
+callsEHReturn:   false
+callsUnwindInit: false
+hasEHCatchret:   false
+hasEHScopes:     false
+hasEHFunclets:   false
+isOutlined:      false
+debugInstrRef:   false
+failsVerification: false
+tracksDebugUserValues: false
+registers:
+  - { id: 0, class: gpr, preferred-register: '' }
+  - { id: 1, class: gpr, preferred-register: '' }
+  - { id: 2, class: gpr, preferred-register: '' }
+liveins:         []
+frameInfo:
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    4
+  adjustsStack:    true
+  hasCalls:        true
+  stackProtector:  ''
+  functionContext: ''
+  maxCallFrameSize: 0
+  cvBytesOfCalleeSavedRegisters: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  hasTailCall:     false
+  localFrameSize:  4
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      []
+stack:
+  - { id: 0, name: c, type: default, offset: 0, size: 4, alignment: 4, 
+      stack-id: default, callee-saved-register: '', callee-saved-restored: true, 
+      local-offset: -4, debug-info-variable: '', debug-info-expression: '', 
+      debug-info-location: '' }
+callSites:       []
+debugValueSubstitutions: []
+constants:       []
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    DBG_VALUE 13, $noreg, !11, !DIExpression(), debug-location !13
+    %0:gpr = MOVi 13, 14 /* CC::al */, $noreg, $noreg
+    STRi12 killed %0, %stack.0.c, 0, 14 /* CC::al */, $noreg, debug-location !14 :: (volatile store (s32) into %ir.c)
+    ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp, debug-location !15
+    BL @_Z4funcv, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $r0, debug-location !15
+    ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp, debug-location !15
+    %1:gpr = COPY $r0, debug-location !15
+    DBG_VALUE %1, $noreg, !11, !DIExpression(), debug-location !13
+    STRi12 %1, %stack.0.c, 0, 14 /* CC::al */, $noreg, debug-location !15 :: (volatile store (s32) into %ir.c)
+    DBG_VALUE %stack.0.c, $noreg, !11, !DIExpression(DW_OP_deref), debug-location !13
+    %2:gpr = LDRi12 %stack.0.c, 0, 14 /* CC::al */, $noreg, debug-location !16 :: (volatile dereferenceable load (s32) from %ir.c)
+    $r0 = COPY %2, debug-location !16
+    BX_RET 14 /* CC::al */, $noreg, implicit $r0, debug-location !16
+
+...

diff  --git a/llvm/test/DebugInfo/ARM/move-dbg-values.mir b/llvm/test/DebugInfo/ARM/move-dbg-values.mir
new file mode 100644
index 0000000000000..1d2f07d8b8d6b
--- /dev/null
+++ b/llvm/test/DebugInfo/ARM/move-dbg-values.mir
@@ -0,0 +1,60 @@
+# RUN: llc %s -start-after=arm-mve-vpt-opts -stop-after=arm-prera-ldst-opt -o - | FileCheck %s
+# CHECK: %5:rgpr = t2MOVCCr %3, killed %4, 0 /* CC::eq */, $cpsr, debug-location !15
+# CHECK-NEXT: DBG_VALUE 0, $noreg, !10, !DIExpression(), debug-location !15
+# CHECK-NEXT: DBG_VALUE $noreg, $noreg, !10, !DIExpression(), debug-location !15
+# CHECK-NEXT: DBG_VALUE $noreg, $noreg, !10, !DIExpression(), debug-location !15
+# CHECK-NEXT: %0:rgpr = t2LDRi12 %5, 0, 14 /* CC::al */, $noreg, debug-location !15 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+# CHECK-NEXT: %6:rgpr = t2LDRi12 %5, 4, 14 /* CC::al */, $noreg, debug-location !15 :: (load (s32) from %ir.btc_user_copy)
+# CHECK-NEXT: DBG_VALUE %6, $noreg, !10, !DIExpression(), debug-location !15
+# CHECK-NEXT: %2:gpr = t2LDRi12 %5, 8, 14 /* CC::al */, $noreg, debug-location !15 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+# CHECK-NEXT: %7:rgpr = t2ANDrr %6, %0, 14 /* CC::al */, $noreg, def $cpsr
+# CHECK-NEXT: DBG_VALUE %2, $noreg, !10, !DIExpression(), debug-location !15
+--- |
+  target triple = "thumbv7k-apple-watchos8.0.0"
+  %struct.backtrace_control = type {}
+  @backtrace_user.ctl_default = internal unnamed_addr constant %struct.backtrace_control zeroinitializer, !dbg !0
+  define i32 @backtrace_user(ptr nocapture noundef writeonly %bt, i32 noundef %max_frames, ptr noundef readonly %ctl_in, ptr nocapture noundef readnone %info_out) local_unnamed_addr #0 !dbg !2 {entry:
+    %tobool.not = icmp eq ptr %ctl_in, null, !dbg !95
+    %.backtrace_user.ctl_default = select i1 %tobool.not, ptr @backtrace_user.ctl_default, ptr %ctl_in, !dbg !95
+    %btc_user_copy = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    %btc_user_copy_context = getelementptr inbounds %struct.backtrace_control, ptr %.backtrace_user.ctl_default, !dbg !95
+    ret i32 undef, !dbg !95
+  }
+  !llvm.module.flags = !{!88,
+   !93}
+  !llvm.dbg.cu = !{!32}
+  !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+  !1 = distinct !DIGlobalVariable(type: !11, isDefinition: true)
+  !2 = distinct !DISubprogram(unit: !32, retainedNodes: !38)
+  !3 = !DIFile(filename: "backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !8 = !DIDerivedType(tag: DW_TAG_typedef, baseType: !11, size: 32)
+  !11 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !12)
+  !12 = distinct !DICompositeType(tag: DW_TAG_structure_type, size: 32)
+  !22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !31, size: 32)
+  !31 = !DICompositeType(tag: DW_TAG_structure_type, flags: DIFlagFwdDecl)
+  !32 = distinct !DICompileUnit(language: DW_LANG_C11, file: !33, sdk: "MacOSX13.0.sdk")
+  !33 = !DIFile(filename: "/Users/shubham/Development/Delta/backtrace.pp.c", directory: "/Users/shubham/Development/Delta")
+  !38 = !{!60, !85}
+  !60 = !DILocalVariable(scope: !2, type: !22)
+  !85 = !DILabel(scope: !2, name: "out", file: !3, line: 102)
+  !88 = !{i32 2, !"Debug Info Version", i32 3}
+  !93 = !{i32 7, !"frame-pointer", i32 1}
+  !95 = !DILocation(line: 5, column: 10, scope: !2)
+name:            backtrace_user
+registers:
+  - {id: 0, class: rgpr, }
+  - {id: 1, class: gpr, }
+  - {id: 2, class: gpr, }
+body:             |
+  bb.0.entry:
+    %10:rgpr = COPY $r2
+    %13:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @backtrace_user.ctl_default, debug-location !95
+    %15:rgpr = t2MOVCCr %10, killed %13, 0 /* CC::eq */, $cpsr, debug-location !95
+    DBG_VALUE 0, $noreg, !60, !DIExpression(), debug-location !95
+    %0:rgpr = t2LDRi12 %15, 0, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir..backtrace_user.ctl_default, align 8)
+    DBG_VALUE %0, $noreg, !60, !DIExpression(), debug-location !95
+    %16:rgpr = t2LDRi12 %15, 4, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy)
+    DBG_VALUE %16, $noreg, !60, !DIExpression(), debug-location !95
+    %2:gpr = t2LDRi12 %15, 8, 14 /* CC::al */, $noreg, debug-location !95 :: (load (s32) from %ir.btc_user_copy_context, align 8)
+    %31:rgpr = t2ANDrr %16, %0, 14 /* CC::al */, $noreg, def $cpsr
+    DBG_VALUE %2, $noreg, !60, !DIExpression(), debug-location !95


        


More information about the llvm-commits mailing list