Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1256,9 +1256,17 @@ "Expected inlined-at fields to agree"); // A dbg.declare describes the address of a source variable, so lower it // into an indirect DBG_VALUE. - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true, - *Op, DI->getVariable(), DI->getExpression()); + auto Builder = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true, *Op, + DI->getVariable(), DI->getExpression()); + + // If using instruction referencing, mutate this into a DBG_INSTR_REF, + // to be later patched up by finalizeDebugInstrRefs. + if (TM.Options.ValueTrackingVariableLocations && Op->isReg()) { + Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); + Builder->getOperand(1).ChangeToImmediate(0); + } } else { // We can't yet handle anything else here because it would require // generating code, thus altering codegen because of debug info. @@ -1301,8 +1309,16 @@ } else if (Register Reg = lookUpRegForValue(V)) { // FIXME: This does not handle register-indirect values at offset 0. bool IsIndirect = false; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg, - DI->getVariable(), DI->getExpression()); + auto Builder = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg, + DI->getVariable(), DI->getExpression()); + + // If using instruction referencing, mutate this into a DBG_INSTR_REF, + // to be later patched up by finalizeDebugInstrRefs. + if (TM.Options.ValueTrackingVariableLocations) { + Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); + Builder->getOperand(1).ChangeToImmediate(0); + } } else { // We don't know how to handle other cases, so we drop. LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n"); Index: llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll =================================================================== --- llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll +++ llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll @@ -6,6 +6,12 @@ ; RUN: -experimental-debug-variable-locations -verify-machineinstrs \ ; RUN: | FileCheck %s --check-prefix=INSTRREF \ ; RUN: --implicit-check-not=DBG_VALUE +; RUN: llc %s -mtriple=x86_64-unknown-unknown -o - -stop-before=finalize-isel \ +; RUN: -experimental-debug-variable-locations -verify-machineinstrs \ +; RUN: -fast-isel \ +; RUN: | FileCheck %s --check-prefix=FASTISEL-INSTRREF \ +; RUN: --implicit-check-not=DBG_VALUE + ; Test that SelectionDAG produces DBG_VALUEs normally, but DBG_INSTR_REFs when ; asked. @@ -30,6 +36,19 @@ ; INSTRREF-SAME: debug-instr-number 2 ; INSTRREF-NEXT: DBG_INSTR_REF 2, 0 +; Test that fast-isel will produce DBG_INSTR_REFs too. + +; FASTISEL-INSTRREF-LABEL: name: foo + +; FASTISEL-INSTRREF: ADD32rr +; FASTISEL-INSTRREF-SAME: debug-instr-number 1 +; FASTISEL-INSTRREF-NEXT: DBG_INSTR_REF 1, 0 +; FASTISEL-INSTRREF-NEXT: ADD32rr +; FASTISEL-INSTRREF-SAME: debug-instr-number 2 +; FASTISEL-INSTRREF-NEXT: DBG_INSTR_REF 2, 0 + + + @glob32 = global i32 0 @glob16 = global i16 0 @glob8 = global i8 0 @@ -87,6 +106,29 @@ ; INSTRREF: DBG_INSTR_REF 4, 0 ; INSTRREF: DBG_INSTR_REF 6, 0 +;; In fast-isel, we get four DBG_INSTR_REFs (compared to three and one +;; DBG_VALUE with normal isel). We get additional substitutions as a result: + +; FASTISEL-INSTRREF: debugValueSubstitutions: +; FASTISEL-INSTRREF-NEXT: - { srcinst: 3, srcop: 0, dstinst: 2, dstop: 0, subreg: 6 } +; FASTISEL-INSTRREF-NEXT: - { srcinst: 5, srcop: 0, dstinst: 4, dstop: 0, subreg: 6 } +; FASTISEL-INSTRREF-NEXT: - { srcinst: 6, srcop: 0, dstinst: 5, dstop: 0, subreg: 4 } +; FASTISEL-INSTRREF-NEXT - { srcinst: 8, srcop: 0, dstinst: 7, dstop: 0, subreg: 6 } +; FASTISEL-INSTRREF-NEXT - { srcinst: 9, srcop: 0, dstinst: 8, dstop: 0, subreg: 4 } +; FASTISEL-INSTRREF-NEXT - { srcinst: 10, srcop: 0, dstinst: 9, dstop: 0, subreg: 1 } + +;; Those substitutions are anchored against these DBG_PHIs: + +; FASTISEL-INSTRREF: DBG_PHI $rdi, 7 +; FASTISEL-INSTRREF-NEXT: DBG_PHI $rdi, 4 +; FASTISEL-INSTRREF-NEXT: DBG_PHI $rdi, 2 +; FASTISEL-INSTRREF-NEXT: DBG_PHI $rdi, 1 + +; FASTISEL-INSTRREF: DBG_INSTR_REF 1, 0 +; FASTISEL-INSTRREF: DBG_INSTR_REF 3, 0 +; FASTISEL-INSTRREF: DBG_INSTR_REF 6, 0 +; FASTISEL-INSTRREF: DBG_INSTR_REF 10, 0 + define i32 @bar(i64 %bar) !dbg !20 { entry: call void @llvm.dbg.value(metadata i64 %bar, metadata !21, metadata !DIExpression()), !dbg !22 @@ -124,9 +166,23 @@ ; INSTRREF: debugValueSubstitutions: ; INSTRREF-NEXT: - { srcinst: 2, srcop: 0, dstinst: 1, dstop: 6, subreg: 4 } -; INSTRREF: CALL64pcrel32 target-flags(x86-plt) @xyzzy, {{.*}} debug-instr-number 1 +; INSTRREF: CALL64pcrel32 target-flags(x86-plt) @xyzzy, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax, debug-instr-number 1 ; INSTRREF: DBG_INSTR_REF 2, 0 +;; Fast-isel produces the same arrangement, a DBG_INSTR_REF pointing back to +;; the call instruction. However: the operand numbers are different (6 for +;; normal isel, 4 for fast-isel). This isn't because of debug-info differences, +;; it's because normal isel implicit-defs the stack registers, and fast-isel +;; does not. The meaning is the same. + +; FASTISEL-INSTRREF-LABEL: name: baz + +; FASTISEL-INSTRREF: debugValueSubstitutions: +; FASTISEL-INSTRREF-NEXT: - { srcinst: 2, srcop: 0, dstinst: 1, dstop: 4, subreg: 4 } + +; FASTISEL-INSTRREF: CALL64pcrel32 target-flags(x86-plt) @xyzzy, csr_64, implicit $rsp, implicit $ssp, implicit-def $rax, debug-instr-number 1 +; FASTISEL-INSTRREF: DBG_INSTR_REF 2, 0 + declare i64 @xyzzy() define i32 @baz() !dbg !30 {