SmallSet<SlotIndex, 2> trimmedDefs;
/// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo.
- void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
+ void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
+ SlotIndex StopIdx,
DbgValueLocation Loc, bool Spilled, LiveIntervals &LIS,
- const TargetInstrInfo &TII);
+ const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI);
/// splitLocation - Replace OldLocNo ranges with NewRegs ranges where NewRegs
/// is live. Returns true if any changes were made.
/// emitDebugValues - Recreate DBG_VALUE instruction from data structures.
void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
- const TargetInstrInfo &TRI,
+ const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI,
const BitVector &SpilledLocations);
/// getDebugLoc - Return DebugLoc of this UserValue.
}
}
-/// findInsertLocation - Find an iterator for inserting a DBG_VALUE
-/// instruction.
+/// Find an iterator for inserting a DBG_VALUE instruction.
static MachineBasicBlock::iterator
findInsertLocation(MachineBasicBlock *MBB, SlotIndex Idx,
LiveIntervals &LIS) {
std::next(MachineBasicBlock::iterator(MI));
}
-void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
+/// Find an iterator for inserting the next DBG_VALUE instruction
+/// (or end if no more insert locations found).
+static MachineBasicBlock::iterator
+findNextInsertLocation(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator I,
+ SlotIndex StopIdx, MachineOperand &LocMO,
+ LiveIntervals &LIS,
+ const TargetRegisterInfo &TRI) {
+ if (!LocMO.isReg())
+ return MBB->instr_end();
+ unsigned Reg = LocMO.getReg();
+
+ // Find the next instruction in the MBB that define the register Reg.
+ while (I != MBB->end()) {
+ if (!LIS.isNotInMIMap(*I) &&
+ SlotIndex::isEarlierEqualInstr(StopIdx, LIS.getInstructionIndex(*I)))
+ break;
+ if (I->definesRegister(Reg, &TRI))
+ // The insert location is directly after the instruction/bundle.
+ return std::next(I);
+ ++I;
+ }
+ return MBB->end();
+}
+
+void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
+ SlotIndex StopIdx,
DbgValueLocation Loc, bool Spilled,
LiveIntervals &LIS,
- const TargetInstrInfo &TII) {
- MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS);
+ const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI) {
+ SlotIndex MBBEndIdx = LIS.getMBBEndIdx(&*MBB);
+ // Only search within the current MBB.
+ StopIdx = (MBBEndIdx < StopIdx) ? MBBEndIdx : StopIdx;
+ MachineBasicBlock::iterator I = findInsertLocation(MBB, StartIdx, LIS);
MachineOperand &MO = locations[Loc.locNo()];
++NumInsertedDebugValues;
assert((!Spilled || MO.isFI()) && "a spilled location must be a frame index");
- MachineInstrBuilder MIB =
+ do {
+ MachineInstrBuilder MIB =
BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
.add(MO);
- if (IsIndirect)
- MIB.addImm(0U);
- else
- MIB.addReg(0U, RegState::Debug);
- MIB.addMetadata(Variable).addMetadata(Expr);
+ if (IsIndirect)
+ MIB.addImm(0U);
+ else
+ MIB.addReg(0U, RegState::Debug);
+ MIB.addMetadata(Variable).addMetadata(Expr);
+
+ // Continue and insert DBG_VALUES after every redefinition of register
+ // associated with the debug value within the range
+ I = findNextInsertLocation(MBB, I, StopIdx, MO, LIS, TRI);
+ } while (I != MBB->end());
}
void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI,
const BitVector &SpilledLocations) {
MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();
SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
- insertDebugValue(&*MBB, Start, Loc, Spilled, LIS, TII);
+ insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, LIS, TII, TRI);
// This interval may span multiple basic blocks.
// Insert a DBG_VALUE into each one.
- while(Stop > MBBEnd) {
+ while (Stop > MBBEnd) {
// Move to the next block.
Start = MBBEnd;
if (++MBB == MFEnd)
break;
MBBEnd = LIS.getMBBEndIdx(&*MBB);
DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
- insertDebugValue(&*MBB, Start, Loc, Spilled, LIS, TII);
+ insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, LIS, TII, TRI);
}
DEBUG(dbgs() << '\n');
if (MBB == MFEnd)
for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
DEBUG(userValues[i]->print(dbgs(), TRI));
userValues[i]->rewriteLocations(*VRM, *TRI, SpilledLocations);
- userValues[i]->emitDebugValues(VRM, *LIS, *TII, SpilledLocations);
+ userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpilledLocations);
}
EmitDone = true;
}
--- /dev/null
+; RUN: llc -O1 -filetype=asm -mtriple x86_64-unknown-linux-gnu -mcpu=x86-64 -o - %s -stop-after=livedebugvars | FileCheck %s
+
+; CHECK: %eax = MOV32rm
+; CHECK: DBG_VALUE %eax
+; CHECK: %eax = SHL32rCL killed %eax
+; CHECK: DBG_VALUE %eax
+; CHECK: DBG_VALUE %rsp, 0, !{{[0-9]+}}, !DIExpression(DW_OP_constu, 4, DW_OP_minus)
+; CHECK: DBG_VALUE %eax
+; CHECK: %eax = SHL32rCL killed %eax
+; CHECK: DBG_VALUE %eax
+; CHECK: RETQ %eax
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@var = local_unnamed_addr global i32 8, !dbg !0
+@sc = local_unnamed_addr global i32 1, !dbg !6
+
+define i32 @main() local_unnamed_addr !dbg !14 {
+entry:
+ %0 = load i32, i32* @var
+ tail call void @llvm.dbg.value(metadata i32 %0, metadata !18, metadata !DIExpression()), !dbg !20
+ %1 = load i32, i32* @sc
+ %shl = shl i32 %0, %1
+ tail call void @llvm.dbg.value(metadata i32 %shl, metadata !18, metadata !DIExpression()), !dbg !20
+ tail call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"(), !srcloc !25
+ %2 = load i32, i32* @sc
+ %shl2 = shl i32 %shl, %2
+ tail call void @llvm.dbg.value(metadata i32 %shl2, metadata !18, metadata !DIExpression()), !dbg !20
+ store i32 %shl2, i32* @var
+ ret i32 %shl2
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10, !11, !12}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "var", scope: !2, file: !3, line: 10, type: !9, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "bar.c", directory: ".")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "sc", scope: !2, file: !3, line: 11, type: !8, isLocal: false, isDefinition: true)
+!8 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 4}
+!14 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 12, type: !15, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: true, unit: !2, variables: !17)
+!15 = !DISubroutineType(types: !16)
+!16 = !{!9}
+!17 = !{!18}
+!18 = !DILocalVariable(name: "bazinga", scope: !14, file: !3, line: 13, type: !9)
+!20 = !DILocation(line: 13, column: 7, scope: !14)
+!25 = !{i32 -2147471481}