[llvm] c4e7857 - [DebugInstrRef] Create DBG_INSTR_REFs in SelectionDAG
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 14 06:24:49 PDT 2020
Author: Jeremy Morse
Date: 2020-10-14T14:24:08+01:00
New Revision: c4e7857d4eaccbd23cdc155486d5c276c8d66ebd
URL: https://github.com/llvm/llvm-project/commit/c4e7857d4eaccbd23cdc155486d5c276c8d66ebd
DIFF: https://github.com/llvm/llvm-project/commit/c4e7857d4eaccbd23cdc155486d5c276c8d66ebd.diff
LOG: [DebugInstrRef] Create DBG_INSTR_REFs in SelectionDAG
When given the -experimental-debug-variable-locations option (via -Xclang
or to llc), have SelectionDAG generate DBG_INSTR_REF instructions instead
of DBG_VALUE. For now, this only happens in a limited circumstance: when
the value referred to is not a PHI and is defined in the current block.
Other situations introduce interesting problems, addresed in later patches.
Practically, this patch hooks into InstrEmitter and if it can find a
defining instruction for a value, gives it an instruction number, and
points the DBG_INSTR_REF at that <instr, operand> pair.
Differential Revision: https://reviews.llvm.org/D85747
Added:
llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index be6f2254a858..95272d56f697 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -695,6 +695,11 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
return &*MIB;
}
+ // Attempt to produce a DBG_INSTR_REF if we've been asked to.
+ if (EmitDebugInstrRefs)
+ if (auto *InstrRef = EmitDbgInstrRef(SD, VRBaseMap))
+ return InstrRef;
+
if (SD->getKind() == SDDbgValue::FRAMEIX) {
// Stack address; this needs to be lowered in target-dependent fashion.
// EmitTargetCodeForFrameDebugValue is responsible for allocation.
@@ -761,6 +766,63 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
return &*MIB;
}
+MachineInstr *
+InstrEmitter::EmitDbgInstrRef(SDDbgValue *SD,
+ DenseMap<SDValue, Register> &VRBaseMap) {
+ // Instruction referencing is still in a prototype state: for now we're only
+ // going to support SDNodes within a block. Copies are not supported, they
+ // don't actually define a value.
+ if (SD->getKind() != SDDbgValue::SDNODE)
+ return nullptr;
+
+ SDNode *Node = SD->getSDNode();
+ SDValue Op = SDValue(Node, SD->getResNo());
+ DenseMap<SDValue, Register>::iterator I = VRBaseMap.find(Op);
+ if (I==VRBaseMap.end())
+ return nullptr; // undef value: let EmitDbgValue produce a DBG_VALUE $noreg.
+
+ MDNode *Var = SD->getVariable();
+ MDNode *Expr = SD->getExpression();
+ DebugLoc DL = SD->getDebugLoc();
+
+ // Try to pick out a defining instruction at this point.
+ unsigned VReg = getVR(Op, VRBaseMap);
+ MachineInstr *ResultInstr = nullptr;
+
+ // No definition corresponds to scenarios where a vreg is live-in to a block,
+ // and doesn't have a defining instruction (yet). This can be patched up
+ // later; at this early stage of implementation, fall back to using DBG_VALUE.
+ if (!MRI->hasOneDef(VReg))
+ return nullptr;
+
+ MachineInstr &DefMI = *MRI->def_instr_begin(VReg);
+ // Some target specific opcodes can become copies. As stated above, we're
+ // ignoring those for now.
+ if (DefMI.isCopy() || DefMI.getOpcode() == TargetOpcode::SUBREG_TO_REG)
+ return nullptr;
+
+ const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_INSTR_REF);
+ auto MIB = BuildMI(*MF, DL, RefII);
+
+ // Find the operand which defines the specified VReg.
+ unsigned OperandIdx = 0;
+ for (const auto &MO : DefMI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg() == VReg)
+ break;
+ ++OperandIdx;
+ }
+ assert(OperandIdx < DefMI.getNumOperands());
+
+ // Make the DBG_INSTR_REF refer to that instruction, and that operand.
+ unsigned InstrNum = DefMI.getDebugInstrNum();
+ MIB.addImm(InstrNum);
+ MIB.addImm(OperandIdx);
+ MIB.addMetadata(Var);
+ MIB.addMetadata(Expr);
+ ResultInstr = &*MIB;
+ return ResultInstr;
+}
+
MachineInstr *
InstrEmitter::EmitDbgLabel(SDDbgLabel *SD) {
MDNode *Label = SD->getLabel();
@@ -1177,10 +1239,12 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
/// InstrEmitter - Construct an InstrEmitter and set it to start inserting
/// at the given position in the given block.
-InstrEmitter::InstrEmitter(MachineBasicBlock *mbb,
+InstrEmitter::InstrEmitter(const TargetMachine &TM, MachineBasicBlock *mbb,
MachineBasicBlock::iterator insertpos)
: MF(mbb->getParent()), MRI(&MF->getRegInfo()),
TII(MF->getSubtarget().getInstrInfo()),
TRI(MF->getSubtarget().getRegisterInfo()),
TLI(MF->getSubtarget().getTargetLowering()), MBB(mbb),
- InsertPos(insertpos) {}
+ InsertPos(insertpos) {
+ EmitDebugInstrRefs = TM.Options.ValueTrackingVariableLocations;
+}
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
index c3567eae9161..d969cb65c5b6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
@@ -37,6 +37,9 @@ class LLVM_LIBRARY_VISIBILITY InstrEmitter {
MachineBasicBlock *MBB;
MachineBasicBlock::iterator InsertPos;
+ /// Should we try to produce DBG_INSTR_REF instructions?
+ bool EmitDebugInstrRefs;
+
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void EmitCopyFromReg(SDNode *Node, unsigned ResNo,
@@ -109,6 +112,11 @@ class LLVM_LIBRARY_VISIBILITY InstrEmitter {
MachineInstr *EmitDbgValue(SDDbgValue *SD,
DenseMap<SDValue, Register> &VRBaseMap);
+ /// Attempt to emit a dbg_value as a DBG_INSTR_REF. May fail and return
+ /// nullptr, in which case we fall back to plain EmitDbgValue.
+ MachineInstr *EmitDbgInstrRef(SDDbgValue *SD,
+ DenseMap<SDValue, Register> &VRBaseMap);
+
/// Generate machine instruction for a dbg_label node.
MachineInstr *EmitDbgLabel(SDDbgLabel *SD);
@@ -130,7 +138,8 @@ class LLVM_LIBRARY_VISIBILITY InstrEmitter {
/// InstrEmitter - Construct an InstrEmitter and set it to start inserting
/// at the given position in the given block.
- InstrEmitter(MachineBasicBlock *mbb, MachineBasicBlock::iterator insertpos);
+ InstrEmitter(const TargetMachine &TM, MachineBasicBlock *mbb,
+ MachineBasicBlock::iterator insertpos);
private:
void EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
index 2902c96c7658..0022e5ec31f0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
@@ -760,7 +760,7 @@ void ScheduleDAGLinearize::Schedule() {
MachineBasicBlock*
ScheduleDAGLinearize::EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
- InstrEmitter Emitter(BB, InsertPos);
+ InstrEmitter Emitter(DAG->getTarget(), BB, InsertPos);
DenseMap<SDValue, Register> VRBaseMap;
LLVM_DEBUG({ dbgs() << "\n*** Final schedule ***\n"; });
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 76fb0340a7a8..e9a84031cc87 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -829,7 +829,7 @@ EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, Register> &VRBaseMap,
/// not necessarily refer to returned BB. The emitter may split blocks.
MachineBasicBlock *ScheduleDAGSDNodes::
EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
- InstrEmitter Emitter(BB, InsertPos);
+ InstrEmitter Emitter(DAG->getTarget(), BB, InsertPos);
DenseMap<SDValue, Register> VRBaseMap;
DenseMap<SUnit*, Register> CopyVRBaseMap;
SmallVector<std::pair<unsigned, MachineInstr*>, 32> Orders;
diff --git a/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll b/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
new file mode 100644
index 000000000000..62ff23a73881
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
@@ -0,0 +1,54 @@
+; RUN: llc %s -mtriple=x86_64-unknown-unknown -o - -stop-before=finalize-isel \
+; RUN: | FileCheck %s --check-prefix=NORMAL \
+; RUN: --implicit-check-not=debug-instr-number \
+; RUN: --implicit-check-not=DBG_INSTR_REF
+; RUN: llc %s -mtriple=x86_64-unknown-unknown -o - -stop-before=finalize-isel \
+; RUN: -experimental-debug-variable-locations -verify-machineinstrs \
+; RUN: | FileCheck %s --check-prefix=INSTRREF \
+; RUN: --implicit-check-not=DBG_VALUE
+
+; Test that SelectionDAG produces DBG_VALUEs normally, but DBG_INSTR_REFs when
+; asked.
+
+; NORMAL: %[[REG0:[0-9]+]]:gr32 = ADD32rr
+; NORMAL-NEXT: DBG_VALUE %[[REG0]]
+; NORMAL-NEXT: %[[REG1:[0-9]+]]:gr32 = ADD32rr
+; NORMAL-NEXT: DBG_VALUE %[[REG1]]
+
+; Note that I'm baking in an assumption of one-based ordering here. We could
+; capture and check for the instruction numbers, we'd rely on machine verifier
+; ensuring there were no duplicates.
+
+; INSTRREF: ADD32rr
+; INSTRREF-SAME: debug-instr-number 1
+; INSTRREF-NEXT: DBG_INSTR_REF 1, 0
+; INSTRREF-NEXT: ADD32rr
+; INSTRREF-SAME: debug-instr-number 2
+; INSTRREF-NEXT: DBG_INSTR_REF 2, 0
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+define i32 @foo(i32 %bar, i32 %baz, i32 %qux) !dbg !7 {
+entry:
+ %0 = add i32 %bar, %baz, !dbg !14
+ call void @llvm.dbg.value(metadata i32 %0, metadata !13, metadata !DIExpression()), !dbg !14
+ %1 = add i32 %0, %qux
+ call void @llvm.dbg.value(metadata i32 %1, metadata !13, metadata !DIExpression()), !dbg !14
+ ret i32 %1, !dbg !14
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "exprconflict.c", directory: "/home/jmorse")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!13}
+!13 = !DILocalVariable(name: "baz", scope: !7, file: !1, line: 6, type: !10)
+!14 = !DILocation(line: 1, scope: !7)
More information about the llvm-commits
mailing list