diff options
author | Stephen Tozer <Stephen.Tozer@Sony.com> | 2021-03-04 12:02:28 +0000 |
---|---|---|
committer | Stephen Tozer <Stephen.Tozer@Sony.com> | 2021-03-05 12:32:05 +0000 |
commit | f677413071a2df10fbb68050624696fd4d4ae1cd (patch) | |
tree | ab4cb1f19b521092c0316ca29ff8aade8d6a6fd5 /llvm/lib | |
parent | c52fe0b02172e707aa2ba38cd2e01a1fc70dd0da (diff) | |
download | llvm-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.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/LiveRangeShrink.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MIParser.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineInstr.cpp | 119 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineRegisterInfo.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/CodeGen/PrologEpilogInserter.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/CodeGen/RegAllocFast.cpp | 88 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp | 27 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86OptimizeLEAs.cpp | 47 |
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; } |