aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorStephen Tozer <Stephen.Tozer@Sony.com>2021-03-04 12:02:28 +0000
committerStephen Tozer <Stephen.Tozer@Sony.com>2021-03-05 12:32:05 +0000
commitf677413071a2df10fbb68050624696fd4d4ae1cd (patch)
treeab4cb1f19b521092c0316ca29ff8aade8d6a6fd5 /llvm/lib
parentc52fe0b02172e707aa2ba38cd2e01a1fc70dd0da (diff)
downloadllvm-f677413071a2df10fbb68050624696fd4d4ae1cd.zip
llvm-f677413071a2df10fbb68050624696fd4d4ae1cd.tar.gz
llvm-f677413071a2df10fbb68050624696fd4d4ae1cd.tar.bz2
Reapply "[DebugInfo] Add new instruction and DIExpression operator for variadic debug values"
Rewrites test to use correct architecture triple; fixes incorrect reference in SourceLevelDebugging doc; simplifies `spillReg` behaviour so as to not be dependent on changes elsewhere in the patch stack. This reverts commit d2000b45d033c06dc7973f59909a0ad12887ff51.
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/BinaryFormat/Dwarf.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp3
-rw-r--r--llvm/lib/CodeGen/LiveRangeShrink.cpp2
-rw-r--r--llvm/lib/CodeGen/MIRParser/MIParser.cpp4
-rw-r--r--llvm/lib/CodeGen/MachineInstr.cpp119
-rw-r--r--llvm/lib/CodeGen/MachineRegisterInfo.cpp6
-rw-r--r--llvm/lib/CodeGen/PrologEpilogInserter.cpp42
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp88
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp26
-rw-r--r--llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp5
-rw-r--r--llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp27
-rw-r--r--llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp14
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp2
-rw-r--r--llvm/lib/Target/X86/X86OptimizeLEAs.cpp47
14 files changed, 277 insertions, 111 deletions
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index e474736..c884257 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -153,6 +153,8 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
return "DW_OP_LLVM_entry_value";
case DW_OP_LLVM_implicit_pointer:
return "DW_OP_LLVM_implicit_pointer";
+ case DW_OP_LLVM_arg:
+ return "DW_OP_LLVM_arg";
}
}
@@ -166,6 +168,7 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
.Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
.Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value)
.Case("DW_OP_LLVM_implicit_pointer", DW_OP_LLVM_implicit_pointer)
+ .Case("DW_OP_LLVM_arg", DW_OP_LLVM_arg)
.Default(0);
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 9eaf486..37d87982 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -905,7 +905,7 @@ static void emitKill(const MachineInstr *MI, AsmPrinter &AP) {
/// means the target will need to handle MI in EmitInstruction.
static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
// This code handles only the 4-operand target-independent form.
- if (MI->getNumOperands() != 4)
+ if (MI->isNonListDebugValue() && MI->getNumOperands() != 4)
return false;
SmallString<128> Str;
@@ -1228,6 +1228,7 @@ void AsmPrinter::emitFunctionBody() {
emitInlineAsm(&MI);
break;
case TargetOpcode::DBG_VALUE:
+ case TargetOpcode::DBG_VALUE_LIST:
if (isVerbose()) {
if (!emitDebugValueComment(&MI, *this))
emitInstruction(&MI);
diff --git a/llvm/lib/CodeGen/LiveRangeShrink.cpp b/llvm/lib/CodeGen/LiveRangeShrink.cpp
index 7fa14fd..6c03a87 100644
--- a/llvm/lib/CodeGen/LiveRangeShrink.cpp
+++ b/llvm/lib/CodeGen/LiveRangeShrink.cpp
@@ -235,7 +235,7 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
MachineBasicBlock::iterator EndIter = std::next(MI.getIterator());
if (MI.getOperand(0).isReg())
for (; EndIter != MBB.end() && EndIter->isDebugValue() &&
- EndIter->getDebugOperandForReg(MI.getOperand(0).getReg());
+ EndIter->hasDebugOperandForReg(MI.getOperand(0).getReg());
++EndIter, ++Next)
IOM[&*EndIter] = NewOrder;
MBB.splice(I, &MBB, MI.getIterator(), EndIter);
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 7b3050d..f41bd27 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -987,7 +987,9 @@ bool MIParser::parse(MachineInstr *&MI) {
Optional<unsigned> TiedDefIdx;
if (parseMachineOperandAndTargetFlags(OpCode, Operands.size(), MO, TiedDefIdx))
return true;
- if (OpCode == TargetOpcode::DBG_VALUE && MO.isReg())
+ if ((OpCode == TargetOpcode::DBG_VALUE ||
+ OpCode == TargetOpcode::DBG_VALUE_LIST) &&
+ MO.isReg())
MO.setIsDebug();
Operands.push_back(
ParsedMachineOperand(MO, Loc, Token.location(), TiedDefIdx));
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 94afaff..f0b2eaa 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -841,28 +841,35 @@ const DILabel *MachineInstr::getDebugLabel() const {
}
const MachineOperand &MachineInstr::getDebugVariableOp() const {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return getOperand(2);
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned VariableOp = isDebugValueList() ? 0 : 2;
+ return getOperand(VariableOp);
}
MachineOperand &MachineInstr::getDebugVariableOp() {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return getOperand(2);
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned VariableOp = isDebugValueList() ? 0 : 2;
+ return getOperand(VariableOp);
}
const DILocalVariable *MachineInstr::getDebugVariable() const {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return cast<DILocalVariable>(getOperand(2).getMetadata());
+ return cast<DILocalVariable>(getDebugVariableOp().getMetadata());
+}
+
+const MachineOperand &MachineInstr::getDebugExpressionOp() const {
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned ExpressionOp = isDebugValueList() ? 1 : 3;
+ return getOperand(ExpressionOp);
}
MachineOperand &MachineInstr::getDebugExpressionOp() {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return getOperand(3);
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned ExpressionOp = isDebugValueList() ? 1 : 3;
+ return getOperand(ExpressionOp);
}
const DIExpression *MachineInstr::getDebugExpression() const {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return cast<DIExpression>(getOperand(3).getMetadata());
+ return cast<DIExpression>(getDebugExpressionOp().getMetadata());
}
bool MachineInstr::isDebugEntryValue() const {
@@ -1712,7 +1719,7 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
OS << " ";
if (isDebugValue() && MO.isMetadata()) {
- // Pretty print DBG_VALUE instructions.
+ // Pretty print DBG_VALUE* instructions.
auto *DIV = dyn_cast<DILocalVariable>(MO.getMetadata());
if (DIV && !DIV->getName().empty())
OS << "!\"" << DIV->getName() << '\"';
@@ -2116,8 +2123,8 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
- MachineOperand &MO, const MDNode *Variable,
- const MDNode *Expr) {
+ const MachineOperand &MO,
+ const MDNode *Variable, const MDNode *Expr) {
assert(isa<DILocalVariable>(Variable) && "not a variable");
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
@@ -2131,7 +2138,28 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
else
MIB.addReg(0U, RegState::Debug);
return MIB.addMetadata(Variable).addMetadata(Expr);
- }
+}
+
+MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ ArrayRef<MachineOperand> MOs,
+ const MDNode *Variable, const MDNode *Expr) {
+ assert(isa<DILocalVariable>(Variable) && "not a variable");
+ assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
+ assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
+ "Expected inlined-at fields to agree");
+ if (MCID.Opcode == TargetOpcode::DBG_VALUE)
+ return BuildMI(MF, DL, MCID, IsIndirect, MOs[0], Variable, Expr);
+
+ auto MIB = BuildMI(MF, DL, MCID);
+ MIB.addMetadata(Variable).addMetadata(Expr);
+ for (const MachineOperand &MO : MOs)
+ if (MO.isReg())
+ MIB.addReg(MO.getReg(), RegState::Debug);
+ else
+ MIB.add(MO);
+ return MIB;
+}
MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
@@ -2155,10 +2183,22 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, *MI);
}
+MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
+ bool IsIndirect, ArrayRef<MachineOperand> MOs,
+ const MDNode *Variable, const MDNode *Expr) {
+ MachineFunction &MF = *BB.getParent();
+ MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, MOs, Variable, Expr);
+ BB.insert(I, MI);
+ 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");
+static const DIExpression *computeExprForSpill(const MachineInstr &MI,
+ Register SpillReg) {
+ assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
"Expected inlined-at fields to agree");
@@ -2167,6 +2207,14 @@ static const DIExpression *computeExprForSpill(const MachineInstr &MI) {
assert(MI.getDebugOffset().getImm() == 0 &&
"DBG_VALUE with nonzero offset");
Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
+ } else if (MI.isDebugValueList()) {
+ // We will replace the spilled register with a frame index, so
+ // immediately deref all references to the spilled register.
+ std::array<uint64_t, 1> Ops{{dwarf::DW_OP_deref}};
+ for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg)) {
+ unsigned OpIdx = MI.getDebugOperandIndex(&Op);
+ Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
+ }
}
return Expr;
}
@@ -2175,18 +2223,32 @@ MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const MachineInstr &Orig,
int FrameIndex) {
- const DIExpression *Expr = computeExprForSpill(Orig);
- return BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc())
- .addFrameIndex(FrameIndex)
- .addImm(0U)
- .addMetadata(Orig.getDebugVariable())
- .addMetadata(Expr);
+ Register SpillReg = Orig.getDebugOperand(0).getReg();
+ const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
+ MachineInstrBuilder NewMI =
+ BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
+ // Non-Variadic Operands: Location, Offset, Variable, Expression
+ // Variadic Operands: Variable, Expression, Locations...
+ if (Orig.isNonListDebugValue())
+ NewMI.addFrameIndex(FrameIndex).addImm(0U);
+ NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
+ if (Orig.isDebugValueList()) {
+ for (const MachineOperand &Op : Orig.debug_operands())
+ if (Op.isReg() && Op.getReg() == SpillReg)
+ NewMI.addFrameIndex(FrameIndex);
+ else
+ NewMI.add(MachineOperand(Op));
+ }
+ return NewMI;
}
void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) {
- const DIExpression *Expr = computeExprForSpill(Orig);
- Orig.getDebugOperand(0).ChangeToFrameIndex(FrameIndex);
- Orig.getDebugOffset().ChangeToImmediate(0U);
+ Register SpillReg = Orig.getDebugOperand(0).getReg();
+ const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
+ if (Orig.isNonListDebugValue())
+ Orig.getDebugOffset().ChangeToImmediate(0U);
+ for (MachineOperand &Op : Orig.getDebugOperandsForReg(SpillReg))
+ Op.ChangeToFrameIndex(FrameIndex);
Orig.getDebugExpressionOp().setMetadata(Expr);
}
@@ -2201,7 +2263,7 @@ void MachineInstr::collectDebugValues(
DI != DE; ++DI) {
if (!DI->isDebugValue())
return;
- if (DI->getDebugOperandForReg(MI.getOperand(0).getReg()))
+ if (DI->hasDebugOperandForReg(MI.getOperand(0).getReg()))
DbgValues.push_back(&*DI);
}
}
@@ -2219,14 +2281,15 @@ void MachineInstr::changeDebugValuesDefReg(Register Reg) {
auto *DI = MO.getParent();
if (!DI->isDebugValue())
continue;
- if (DI->getDebugOperandForReg(DefReg)) {
+ if (DI->hasDebugOperandForReg(DefReg)) {
DbgValues.push_back(DI);
}
}
// Propagate Reg to debug value instructions.
for (auto *DBI : DbgValues)
- DBI->getDebugOperandForReg(DefReg)->setReg(Reg);
+ for (MachineOperand &Op : DBI->getDebugOperandsForReg(DefReg))
+ Op.setReg(Reg);
}
using MMOList = SmallVector<const MachineMemOperand *, 2>;
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index d7444ec..58bb866 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -530,11 +530,11 @@ bool MachineRegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
/// specified register as undefined which causes the DBG_VALUE to be
/// deleted during LiveDebugVariables analysis.
void MachineRegisterInfo::markUsesInDebugValueAsUndef(Register Reg) const {
- // Mark any DBG_VALUE that uses Reg as undef (but don't delete it.)
+ // Mark any DBG_VALUE* that uses Reg as undef (but don't delete it.)
// We use make_early_inc_range because setReg invalidates the iterator.
for (MachineInstr &UseMI : llvm::make_early_inc_range(use_instructions(Reg))) {
- if (UseMI.isDebugValue())
- UseMI.getDebugOperandForReg(Reg)->setReg(0U);
+ if (UseMI.isDebugValue() && UseMI.hasDebugOperandForReg(Reg))
+ UseMI.setDebugValueUndef();
}
}
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 84bb292..91c6911 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -1233,23 +1233,33 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
// complex location that is interpreted as being a memory address.
// This changes a pointer-valued variable to dereference that pointer,
// which is incorrect. Fix by adding DW_OP_stack_value.
- unsigned PrependFlags = DIExpression::ApplyOffset;
- if (!MI.isIndirectDebugValue() && !DIExpr->isComplex())
- PrependFlags |= DIExpression::StackValue;
-
- // If we have DBG_VALUE that is indirect and has a Implicit location
- // expression need to insert a deref before prepending a Memory
- // location expression. Also after doing this we change the DBG_VALUE
- // to be direct.
- if (MI.isIndirectDebugValue() && DIExpr->isImplicit()) {
- SmallVector<uint64_t, 2> Ops = {dwarf::DW_OP_deref_size, Size};
- bool WithStackValue = true;
- DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue);
- // Make the DBG_VALUE direct.
- MI.getDebugOffset().ChangeToRegister(0, false);
- }
- DIExpr = TRI.prependOffsetExpression(DIExpr, PrependFlags, Offset);
+ if (MI.isNonListDebugValue()) {
+ unsigned PrependFlags = DIExpression::ApplyOffset;
+ if (!MI.isIndirectDebugValue() && !DIExpr->isComplex())
+ PrependFlags |= DIExpression::StackValue;
+
+ // If we have DBG_VALUE that is indirect and has a Implicit location
+ // expression need to insert a deref before prepending a Memory
+ // location expression. Also after doing this we change the DBG_VALUE
+ // to be direct.
+ if (MI.isIndirectDebugValue() && DIExpr->isImplicit()) {
+ SmallVector<uint64_t, 2> Ops = {dwarf::DW_OP_deref_size, Size};
+ bool WithStackValue = true;
+ DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue);
+ // Make the DBG_VALUE direct.
+ MI.getDebugOffset().ChangeToRegister(0, false);
+ }
+ DIExpr = TRI.prependOffsetExpression(DIExpr, PrependFlags, Offset);
+ } else {
+ // The debug operand at DebugOpIndex was a frame index at offset
+ // `Offset`; now the operand has been replaced with the frame
+ // register, we must add Offset with `register x, plus Offset`.
+ unsigned DebugOpIndex = MI.getDebugOperandIndex(&MI.getOperand(i));
+ SmallVector<uint64_t, 3> Ops;
+ TRI.getOffsetOpcodes(Offset, Ops);
+ DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, DebugOpIndex);
+ }
MI.getDebugExpressionOp().setMetadata(DIExpr);
continue;
}
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 256faa2..5690023b 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -424,9 +424,14 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
}
// Rewrite unassigned dbg_values to use the stack slot.
- MachineOperand &MO = DBG->getOperand(0);
- if (MO.isReg() && MO.getReg() == 0)
- updateDbgValueForSpill(*DBG, FI);
+ // TODO We can potentially do this for list debug values as well if we know
+ // how the dbg_values are getting unassigned.
+ if (DBG->isNonListDebugValue()) {
+ MachineOperand &MO = DBG->getDebugOperand(0);
+ if (MO.isReg() && MO.getReg() == 0) {
+ updateDbgValueForSpill(*DBG, FI);
+ }
+ }
}
// Now this register is spilled there is should not be any DBG_VALUE
// pointing to this register because they are all pointing to spilled value
@@ -623,8 +628,7 @@ void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition,
SmallVectorImpl<MachineInstr*> &Dangling = UDBGValIter->second;
for (MachineInstr *DbgValue : Dangling) {
assert(DbgValue->isDebugValue());
- MachineOperand &MO = DbgValue->getOperand(0);
- if (!MO.isReg())
+ if (!DbgValue->hasDebugOperandForReg(VirtReg))
continue;
// Test whether the physreg survives from the definition to the DBG_VALUE.
@@ -639,9 +643,11 @@ void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition,
break;
}
}
- MO.setReg(SetToReg);
- if (SetToReg != 0)
- MO.setIsRenamable();
+ for (MachineOperand &MO : DbgValue->getDebugOperandsForReg(VirtReg)) {
+ MO.setReg(SetToReg);
+ if (SetToReg != 0)
+ MO.setIsRenamable();
+ }
}
Dangling.clear();
}
@@ -1360,37 +1366,44 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
}
void RegAllocFast::handleDebugValue(MachineInstr &MI) {
- MachineOperand &MO = MI.getDebugOperand(0);
+ SmallSet<Register, 4> SeenRegisters;
+ for (MachineOperand &MO : MI.debug_operands()) {
+ // Ignore DBG_VALUEs that aren't based on virtual registers. These are
+ // mostly constants and frame indices.
+ if (!MO.isReg())
+ continue;
+ Register Reg = MO.getReg();
+ if (!Register::isVirtualRegister(Reg))
+ continue;
+ // Only process each register once per MI, each use of that register will
+ // be updated if necessary.
+ if (!SeenRegisters.insert(Reg).second)
+ continue;
- // Ignore DBG_VALUEs that aren't based on virtual registers. These are
- // mostly constants and frame indices.
- if (!MO.isReg())
- return;
- Register Reg = MO.getReg();
- if (!Register::isVirtualRegister(Reg))
- return;
+ // Already spilled to a stackslot?
+ int SS = StackSlotForVirtReg[Reg];
+ if (SS != -1) {
+ // Modify DBG_VALUE now that the value is in a spill slot.
+ updateDbgValueForSpill(MI, SS);
+ LLVM_DEBUG(dbgs() << "Rewrite DBG_VALUE for spilled memory: " << MI);
+ continue;
+ }
- // Already spilled to a stackslot?
- int SS = StackSlotForVirtReg[Reg];
- if (SS != -1) {
- // Modify DBG_VALUE now that the value is in a spill slot.
- updateDbgValueForSpill(MI, SS);
- LLVM_DEBUG(dbgs() << "Rewrite DBG_VALUE for spilled memory: " << MI);
- return;
- }
+ // 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() && LRI->PhysReg) {
+ // Update every use of Reg within MI.
+ for (auto &RegMO : MI.getDebugOperandsForReg(Reg))
+ setPhysReg(MI, RegMO, LRI->PhysReg);
+ } else {
+ DanglingDbgValues[Reg].push_back(&MI);
+ }
- // 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() && LRI->PhysReg) {
- setPhysReg(MI, MO, LRI->PhysReg);
- } else {
- DanglingDbgValues[Reg].push_back(&MI);
+ // 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(&MI);
}
-
- // 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(&MI);
}
void RegAllocFast::handleBundle(MachineInstr &MI) {
@@ -1472,13 +1485,12 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
for (auto &UDBGPair : DanglingDbgValues) {
for (MachineInstr *DbgValue : UDBGPair.second) {
assert(DbgValue->isDebugValue() && "expected DBG_VALUE");
- MachineOperand &MO = DbgValue->getOperand(0);
// Nothing to do if the vreg was spilled in the meantime.
- if (!MO.isReg())
+ if (!DbgValue->hasDebugOperandForReg(UDBGPair.first))
continue;
LLVM_DEBUG(dbgs() << "Register did not survive for " << *DbgValue
<< '\n');
- MO.setReg(0);
+ DbgValue->setDebugValueUndef();
}
}
DanglingDbgValues.clear();
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 973020c..ba2638e 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1059,6 +1059,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
case dwarf::DW_OP_plus_uconst:
case dwarf::DW_OP_LLVM_tag_offset:
case dwarf::DW_OP_LLVM_entry_value:
+ case dwarf::DW_OP_LLVM_arg:
case dwarf::DW_OP_regx:
return 2;
default:
@@ -1115,6 +1116,7 @@ bool DIExpression::isValid() const {
}
case dwarf::DW_OP_LLVM_implicit_pointer:
case dwarf::DW_OP_LLVM_convert:
+ case dwarf::DW_OP_LLVM_arg:
case dwarf::DW_OP_LLVM_tag_offset:
case dwarf::DW_OP_constu:
case dwarf::DW_OP_plus_uconst:
@@ -1270,6 +1272,30 @@ DIExpression *DIExpression::prepend(const DIExpression *Expr, uint8_t Flags,
return prependOpcodes(Expr, Ops, StackValue, EntryValue);
}
+DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr,
+ ArrayRef<uint64_t> Ops,
+ unsigned ArgNo, bool StackValue) {
+ assert(Expr && "Can't add ops to this expression");
+
+ // Handle non-variadic intrinsics by prepending the opcodes.
+ if (!any_of(Expr->expr_ops(),
+ [](auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) {
+ assert(ArgNo == 0 &&
+ "Location Index must be 0 for a non-variadic expression.");
+ SmallVector<uint64_t, 8> NewOps(Ops.begin(), Ops.end());
+ return DIExpression::prependOpcodes(Expr, NewOps, StackValue);
+ }
+
+ SmallVector<uint64_t, 8> NewOps;
+ for (auto Op : Expr->expr_ops()) {
+ Op.appendToVector(NewOps);
+ if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo)
+ NewOps.insert(NewOps.end(), Ops.begin(), Ops.end());
+ }
+
+ return DIExpression::get(Expr->getContext(), NewOps);
+}
+
DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,
SmallVectorImpl<uint64_t> &Ops,
bool StackValue,
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 672efdf..289df8e 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -1210,7 +1210,8 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
}
break;
- case AArch64::DBG_VALUE: {
+ case AArch64::DBG_VALUE:
+ case AArch64::DBG_VALUE_LIST: {
if (isVerbose() && OutStreamer->hasRawTextSupport()) {
SmallString<128> TmpStr;
raw_svector_ostream OS(TmpStr);
@@ -1231,7 +1232,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
OutStreamer->emitCFIBKeyFrame();
return;
}
- }
+ }
// Tail calls use pseudo instructions so they have the proper code-gen
// attributes (isCall, isReturn, etc.). We lower them to the real
diff --git a/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp b/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp
index 756355f..0c1f741 100644
--- a/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp
@@ -65,16 +65,25 @@ bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {
// way with simply the frame index and offset rather than any
// target-specific addressing mode.
if (MI.isDebugValue()) {
- assert(i == 0 && "Frame indices can only appear as the first "
- "operand of a DBG_VALUE machine instruction");
+ MachineOperand &Op = MI.getOperand(i);
+ assert(
+ MI.isDebugOperand(&Op) &&
+ "Frame indices can only appear as a debug operand in a DBG_VALUE*"
+ " machine instruction");
Register Reg;
- int64_t Offset =
- TFI.getFrameIndexReference(MF, MI.getOperand(0).getIndex(), Reg)
- .getFixed();
- MI.getOperand(0).ChangeToRegister(Reg, /*isDef=*/false);
- MI.getOperand(0).setIsDebug();
- auto *DIExpr = DIExpression::prepend(
- MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
+ auto Offset =
+ TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
+ Op.ChangeToRegister(Reg, /*isDef=*/false);
+ Op.setIsDebug();
+ const DIExpression *DIExpr = MI.getDebugExpression();
+ if (MI.isNonListDebugValue()) {
+ DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
+ } else {
+ SmallVector<uint64_t, 3> Ops;
+ TRI.getOffsetOpcodes(Offset, Ops);
+ unsigned OpIdx = MI.getDebugOperandIndex(&Op);
+ DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, OpIdx);
+ }
MI.getDebugExpressionOp().setMetadata(DIExpr);
continue;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 055daf3..da91316 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -9,12 +9,13 @@
#include "SystemZRegisterInfo.h"
#include "SystemZInstrInfo.h"
#include "SystemZSubtarget.h"
-#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/VirtRegMap.h"
+#include "llvm/IR/DebugInfoMetadata.h"
using namespace llvm;
@@ -273,7 +274,16 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
// Special handling of dbg_value instructions.
if (MI->isDebugValue()) {
MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);
- MI->getDebugOffset().ChangeToImmediate(Offset);
+ if (MI->isNonListDebugValue()) {
+ MI->getDebugOffset().ChangeToImmediate(Offset);
+ } else {
+ unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum));
+ SmallVector<uint64_t, 3> Ops;
+ DIExpression::appendOffset(
+ Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed());
+ MI->getDebugExpressionOp().setMetadata(
+ DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx));
+ }
return;
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
index c63656a..d511fde 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
@@ -30,7 +30,7 @@ WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(
for (MachineBasicBlock::iterator DE = Instr->getParent()->end(); DI != DE;
++DI) {
if (DI->isDebugValue() &&
- DI->getDebugOperandForReg(Instr->getOperand(0).getReg()))
+ DI->hasDebugOperandForReg(Instr->getOperand(0).getReg()))
DbgValues.push_back(&*DI);
}
}
diff --git a/llvm/lib/Target/X86/X86OptimizeLEAs.cpp b/llvm/lib/Target/X86/X86OptimizeLEAs.cpp
index c8899a8..220fd0b 100644
--- a/llvm/lib/Target/X86/X86OptimizeLEAs.cpp
+++ b/llvm/lib/Target/X86/X86OptimizeLEAs.cpp
@@ -295,8 +295,8 @@ private:
/// Replace debug value MI with a new debug value instruction using register
/// VReg with an appropriate offset and DIExpression to incorporate the
/// address displacement AddrDispShift. Return new debug value instruction.
- MachineInstr *replaceDebugValue(MachineInstr &MI, unsigned VReg,
- int64_t AddrDispShift);
+ MachineInstr *replaceDebugValue(MachineInstr &MI, unsigned OldReg,
+ unsigned NewReg, int64_t AddrDispShift);
/// Removes LEAs which calculate similar addresses.
bool removeRedundantLEAs(MemOpMap &LEAs);
@@ -576,21 +576,50 @@ bool X86OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
}
MachineInstr *X86OptimizeLEAPass::replaceDebugValue(MachineInstr &MI,
- unsigned VReg,
+ unsigned OldReg,
+ unsigned NewReg,
int64_t AddrDispShift) {
const DIExpression *Expr = MI.getDebugExpression();
- if (AddrDispShift != 0)
- Expr = DIExpression::prepend(Expr, DIExpression::StackValue, AddrDispShift);
+ if (AddrDispShift != 0) {
+ if (MI.isNonListDebugValue()) {
+ Expr =
+ DIExpression::prepend(Expr, DIExpression::StackValue, AddrDispShift);
+ } else {
+ // Update the Expression, appending an offset of `AddrDispShift` to the
+ // Op corresponding to `OldReg`.
+ SmallVector<uint64_t, 3> Ops;
+ DIExpression::appendOffset(Ops, AddrDispShift);
+ for (MachineOperand &Op : MI.getDebugOperandsForReg(OldReg)) {
+ unsigned OpIdx = MI.getDebugOperandIndex(&Op);
+ Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
+ }
+ }
+ }
// Replace DBG_VALUE instruction with modified version.
MachineBasicBlock *MBB = MI.getParent();
DebugLoc DL = MI.getDebugLoc();
bool IsIndirect = MI.isIndirectDebugValue();
const MDNode *Var = MI.getDebugVariable();
+ unsigned Opcode = MI.isNonListDebugValue() ? TargetOpcode::DBG_VALUE
+ : TargetOpcode::DBG_VALUE_LIST;
if (IsIndirect)
- assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset");
- return BuildMI(*MBB, MBB->erase(&MI), DL, TII->get(TargetOpcode::DBG_VALUE),
- IsIndirect, VReg, Var, Expr);
+ assert(MI.getDebugOffset().getImm() == 0 &&
+ "DBG_VALUE with nonzero offset");
+ SmallVector<MachineOperand, 4> NewOps;
+ // If we encounter an operand using the old register, replace it with an
+ // operand that uses the new register; otherwise keep the old operand.
+ auto replaceOldReg = [OldReg, NewReg](const MachineOperand &Op) {
+ if (Op.isReg() && Op.getReg() == OldReg)
+ return MachineOperand::CreateReg(NewReg, false, false, false, false,
+ false, false, false, false, 0,
+ /*IsRenamable*/ true);
+ return Op;
+ };
+ for (const MachineOperand &Op : MI.debug_operands())
+ NewOps.push_back(replaceOldReg(Op));
+ return BuildMI(*MBB, MBB->erase(&MI), DL, TII->get(Opcode), IsIndirect,
+ NewOps, Var, Expr);
}
// Try to find similar LEAs in the list and replace one with another.
@@ -635,7 +664,7 @@ bool X86OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
// Replace DBG_VALUE instruction with modified version using the
// register from the replacing LEA and the address displacement
// between the LEA instructions.
- replaceDebugValue(MI, FirstVReg, AddrDispShift);
+ replaceDebugValue(MI, LastVReg, FirstVReg, AddrDispShift);
continue;
}