diff --git a/llvm/lib/CodeGen/MachineDebugify.cpp b/llvm/lib/CodeGen/MachineDebugify.cpp --- a/llvm/lib/CodeGen/MachineDebugify.cpp +++ b/llvm/lib/CodeGen/MachineDebugify.cpp @@ -12,11 +12,17 @@ /// This isn't intended to have feature parity with Debugify. //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/InitializePasses.h" #include "llvm/Transforms/Utils/Debugify.h" @@ -28,13 +34,39 @@ bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI, DIBuilder &DIB, Function &F) { MachineFunction &MF = MMI.getOrCreateMachineFunction(F); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); DISubprogram *SP = F.getSubprogram(); assert(SP && "IR Debugify just created it?"); - LLVMContext &Ctx = F.getParent()->getContext(); + Module &M = *F.getParent(); + LLVMContext &Ctx = M.getContext(); + + // Find local variables defined by debugify. No attempt is made to match up + // MIR-level vregs to the 'correct' IR-level variables: there isn't a simple + // way to do that, and it isn't necessary to find interesting CodeGen bugs. + // Instead, simply keep track of one variable per line. Later, we can insert + // DBG_VALUE insts that point to these local variables. + Function *DbgValF = M.getFunction("llvm.dbg.value"); + DbgValueInst *EarliestDVI = nullptr; + DenseMap Line2Var; + DIExpression *Expr = nullptr; + if (DbgValF) { + for (const Use &U : DbgValF->uses()) { + auto *DVI = dyn_cast(U.getUser()); + if (!DVI || DVI->getFunction() != &F) + continue; + unsigned Line = DVI->getDebugLoc().getLine(); + assert(Line != 0 && "debugify should not insert line 0 locations"); + Line2Var[Line] = DVI->getVariable(); + if (!EarliestDVI || Line < EarliestDVI->getDebugLoc().getLine()) + EarliestDVI = DVI; + Expr = DVI->getExpression(); + } + } + unsigned NextLine = SP->getLine(); - + SmallVector DefinedValues; for (MachineBasicBlock &MBB : MF) { for (MachineInstr &MI : MBB) { // This will likely emit line numbers beyond the end of the imagined @@ -42,9 +74,35 @@ // that as it doesn't really matter to the compiler where the line is in // the imaginary source code. MI.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); + + // Keep track of defined regs. This lets us insert DBG_VALUEs later. + if (!Line2Var.empty()) + for (MachineOperand &MO : MI.operands()) + if (MO.isReg() && MO.isDef() && MO.getReg()) + DefinedValues.push_back(&MO); } } + if (Line2Var.empty()) + return true; + + // Insert DBG_VALUEs for all defined regs. + const MCInstrDesc &DbgValDesc = TII.get(TargetOpcode::DBG_VALUE); + for (MachineOperand *MO : DefinedValues) { + MachineInstr &MI = *MO->getParent(); + // Just like at the IR level, it's not expected for there to be non-PHI + // instructions in between PHIs at the MIR level. + if (MI.isPHI()) + continue; + unsigned Line = MI.getDebugLoc().getLine(); + if (!Line2Var.count(Line)) + Line = EarliestDVI->getDebugLoc().getLine(); + DILocalVariable *LocalVar = Line2Var[Line]; + assert(LocalVar && "No variable for current line?"); + BuildMI(*MI.getParent(), std::next(MI.getIterator()), MI.getDebugLoc(), + DbgValDesc, /*IsIndirect=*/false, *MO, LocalVar, Expr); + } + return true; } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -O0 -mtriple=aarch64-unknown-unknown -verify-machineinstrs -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -debugify-and-strip-all-safe -O0 -mtriple=aarch64-unknown-unknown -verify-machineinstrs -run-pass=legalizer %s -o - | FileCheck %s --- | target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/CodeGen/Generic/MIRDebugify/locations.mir b/llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir rename from llvm/test/CodeGen/Generic/MIRDebugify/locations.mir rename to llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir --- a/llvm/test/CodeGen/Generic/MIRDebugify/locations.mir +++ b/llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir @@ -17,11 +17,13 @@ ret i32 %sub } - ; CHECK: !llvm.dbg.cu = !{!0} - ; CHECK: !llvm.debugify = - ; CHECK: !llvm.module.flags = !{![[VERSION:[0-9]+]]} - ; CHECK: !0 = distinct !DICompileUnit( - ; CHECK: ![[VERSION]] = !{i32 2, !"Debug Info Version", i32 3} + ; ALL: !llvm.dbg.cu = !{!0} + ; ALL: !llvm.debugify = + ; ALL: !llvm.module.flags = !{![[VERSION:[0-9]+]]} + ; ALL: !0 = distinct !DICompileUnit( + ; ALL: ![[VERSION]] = !{i32 2, !"Debug Info Version", i32 3} + ; VALUE: [[VAR1:![0-9]+]] = !DILocalVariable(name: "1" + ; VALUE: [[VAR2:![0-9]+]] = !DILocalVariable(name: "2" ... --- @@ -37,8 +39,13 @@ ; source file anyway. These first three coincide with IR-level information ; and therefore use metadata references. ; ALL: %0:_(s32) = IMPLICIT_DEF debug-location [[L1]] + ; VALUE: DBG_VALUE %0(s32), $noreg, [[VAR1]], !DIExpression(), debug-location [[L1]] ; ALL: %1:_(s32) = IMPLICIT_DEF debug-location [[L2]] + ; VALUE: DBG_VALUE %1(s32), $noreg, [[VAR2]], !DIExpression(), debug-location [[L2]] ; ALL: %2:_(s32) = G_CONSTANT i32 2, debug-location [[L3]] + ; VALUE: DBG_VALUE %2(s32), $noreg, [[VAR1]], !DIExpression(), debug-location [[L3]] ; ALL: %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: !6) + ; VALUE: DBG_VALUE %3(s32), $noreg, [[VAR1]], !DIExpression(), debug-location !DILocation(line: 4 ; ALL: %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: !6) + ; VALUE: DBG_VALUE %4(s32), $noreg, [[VAR1]], !DIExpression(), debug-location !DILocation(line: 5 ...