summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/CodeGen/MachineInstrBuilder.h4
-rw-r--r--llvm/lib/CodeGen/MachineInstr.cpp40
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp78
-rw-r--r--llvm/test/DebugInfo/X86/dbg-declare-arg.ll18
4 files changed, 76 insertions, 64 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index f452e6d9d46..9e0f19a5aea 100644
--- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -418,6 +418,10 @@ MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
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;
}
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 6684f4e5d1c..66de99156b4 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2408,26 +2408,36 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
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<DIExpression>(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<DILocalVariable>(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);
+}
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index f00a0312dad..7061c3ff652 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -871,56 +871,40 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
// 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<DILocalVariable>(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;
}
diff --git a/llvm/test/DebugInfo/X86/dbg-declare-arg.ll b/llvm/test/DebugInfo/X86/dbg-declare-arg.ll
index 2432de91b21..8115fa7dc87 100644
--- a/llvm/test/DebugInfo/X86/dbg-declare-arg.ll
+++ b/llvm/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 }
OpenPOWER on IntegriCloud