[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