Index: llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h +++ llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h @@ -418,6 +418,10 @@ MachineBasicBlock::iterator I, const MachineInstr &Orig, int FrameIndex); +/// Update a DBG_VALUE whose value has been spilled to FrameIndex. Useful when +/// modifying an instruction in place while iterating over a basic block. +void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex); + inline unsigned getDefRegState(bool B) { return B ? RegState::Define : 0; } Index: llvm/trunk/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineInstr.cpp +++ llvm/trunk/lib/CodeGen/MachineInstr.cpp @@ -2408,26 +2408,36 @@ return MachineInstrBuilder(MF, MI); } +/// Compute the new DIExpression to use with a DBG_VALUE for a spill slot. +/// This prepends DW_OP_deref when spilling an indirect DBG_VALUE. +static const DIExpression *computeExprForSpill(const MachineInstr &MI) { + assert(MI.getOperand(0).isReg() && "can't spill non-register"); + assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) && + "Expected inlined-at fields to agree"); + + const DIExpression *Expr = MI.getDebugExpression(); + if (MI.isIndirectDebugValue()) { + assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset"); + Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); + } + return Expr; +} + MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I, const MachineInstr &Orig, int FrameIndex) { - const MDNode *Var = Orig.getDebugVariable(); - const auto *Expr = cast_or_null(Orig.getDebugExpression()); - bool IsIndirect = Orig.isIndirectDebugValue(); - if (IsIndirect) - assert(Orig.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset"); - DebugLoc DL = Orig.getDebugLoc(); - assert(cast(Var)->isValidLocationForIntrinsic(DL) && - "Expected inlined-at fields to agree"); - // If the DBG_VALUE already was a memory location, add an extra - // DW_OP_deref. Otherwise just turning this from a register into a - // memory/indirect location is sufficient. - if (IsIndirect) - Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); - return BuildMI(BB, I, DL, Orig.getDesc()) + const DIExpression *Expr = computeExprForSpill(Orig); + return BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc()) .addFrameIndex(FrameIndex) .addImm(0U) - .addMetadata(Var) + .addMetadata(Orig.getDebugVariable()) .addMetadata(Expr); } + +void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) { + const DIExpression *Expr = computeExprForSpill(Orig); + Orig.getOperand(0).ChangeToFrameIndex(FrameIndex); + Orig.getOperand(1).ChangeToImmediate(0U); + Orig.getOperand(3).setMetadata(Expr); +} Index: llvm/trunk/lib/CodeGen/RegAllocFast.cpp =================================================================== --- llvm/trunk/lib/CodeGen/RegAllocFast.cpp +++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp @@ -871,56 +871,40 @@ // Debug values are not allowed to change codegen in any way. if (MI.isDebugValue()) { - bool ScanDbgValue = true; MachineInstr *DebugMI = &MI; - while (ScanDbgValue) { - ScanDbgValue = false; - for (unsigned I = 0, E = DebugMI->getNumOperands(); I != E; ++I) { - MachineOperand &MO = DebugMI->getOperand(I); - if (!MO.isReg()) continue; - unsigned Reg = MO.getReg(); - if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; - LiveRegMap::iterator LRI = findLiveVirtReg(Reg); - if (LRI != LiveVirtRegs.end()) - setPhysReg(*DebugMI, I, LRI->PhysReg); - else { - int SS = StackSlotForVirtReg[Reg]; - if (SS == -1) { - // We can't allocate a physreg for a DebugValue, sorry! - DEBUG(dbgs() << "Unable to allocate vreg used by DBG_VALUE"); - MO.setReg(0); - } - else { - // Modify DBG_VALUE now that the value is in a spill slot. - bool IsIndirect = DebugMI->isIndirectDebugValue(); - if (IsIndirect) - assert(DebugMI->getOperand(1).getImm() == 0 && - "DBG_VALUE with nonzero offset"); - const MDNode *Var = DebugMI->getDebugVariable(); - const MDNode *Expr = DebugMI->getDebugExpression(); - DebugLoc DL = DebugMI->getDebugLoc(); - MachineBasicBlock *MBB = DebugMI->getParent(); - assert( - cast(Var)->isValidLocationForIntrinsic(DL) && - "Expected inlined-at fields to agree"); - MachineInstr *NewDV = BuildMI(*MBB, MBB->erase(DebugMI), DL, - TII->get(TargetOpcode::DBG_VALUE)) - .addFrameIndex(SS) - .addImm(0U) - .addMetadata(Var) - .addMetadata(Expr); - DEBUG(dbgs() << "Modifying debug info due to spill:" - << "\t" << *NewDV); - // Scan NewDV operands from the beginning. - DebugMI = NewDV; - ScanDbgValue = true; - break; - } - } - LiveDbgValueMap[Reg].push_back(DebugMI); + MachineOperand &MO = DebugMI->getOperand(0); + + // Ignore DBG_VALUEs that aren't based on virtual registers. These are + // mostly constants and frame indices. + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + // See if this virtual register has already been allocated to a physical + // register or spilled to a stack slot. + LiveRegMap::iterator LRI = findLiveVirtReg(Reg); + if (LRI != LiveVirtRegs.end()) + setPhysReg(*DebugMI, 0, LRI->PhysReg); + else { + int SS = StackSlotForVirtReg[Reg]; + if (SS != -1) { + // Modify DBG_VALUE now that the value is in a spill slot. + updateDbgValueForSpill(*DebugMI, SS); + DEBUG(dbgs() << "Modifying debug info due to spill:" + << "\t" << *DebugMI); + continue; } + + // We can't allocate a physreg for a DebugValue, sorry! + DEBUG(dbgs() << "Unable to allocate vreg used by DBG_VALUE"); + MO.setReg(0); } - // Next instruction. + + // If Reg hasn't been spilled, put this DBG_VALUE in LiveDbgValueMap so + // that future spills of Reg will have DBG_VALUEs. + LiveDbgValueMap[Reg].push_back(DebugMI); continue; } Index: llvm/trunk/test/DebugInfo/X86/dbg-declare-arg.ll =================================================================== --- llvm/trunk/test/DebugInfo/X86/dbg-declare-arg.ll +++ llvm/trunk/test/DebugInfo/X86/dbg-declare-arg.ll @@ -1,12 +1,26 @@ ; RUN: llc -O0 -fast-isel=true -filetype=obj -o - %s | llvm-dwarfdump -v - | FileCheck %s + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-macosx10.6.7" ; rdar://problem/9321650 -; + +; C++ source: +; class A { public: int x; int y; int z; int o; ~A() { x = 1; }}; +; +; A foo(int i) { +; int j = 0; +; if (i == 42) { +; j = i + 1; +; }; +; A my_a; +; my_a.x = j; +; return my_a; +; } + ; CHECK: DW_AT_name {{.*}}"j" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ( -; CHECK-NEXT: 0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+8) +; CHECK-NEXT: 0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+8, DW_OP_deref) ; CHECK-NEXT: DW_AT_name {{.*}}"my_a" %class.A = type { i32, i32, i32, i32 }