diff options
author | Jeremy Morse <jeremy.morse.llvm@gmail.com> | 2019-06-10 15:23:46 +0000 |
---|---|---|
committer | Jeremy Morse <jeremy.morse.llvm@gmail.com> | 2019-06-10 15:23:46 +0000 |
commit | bcff41729209cafa29aa87c978809e3dc90c769a (patch) | |
tree | f8463bc71cabf8ffb5ca6f3de09dd70ad600ac10 /llvm/lib | |
parent | 3dea52725862cc320d05056bfc433ad519fd5084 (diff) | |
download | bcm5719-llvm-bcff41729209cafa29aa87c978809e3dc90c769a.tar.gz bcm5719-llvm-bcff41729209cafa29aa87c978809e3dc90c769a.zip |
[DebugInfo] Terminate all location-lists at end of block
This commit reapplies r359426 (which was reverted in r360301 due to
performance problems) and rolls in D61940 to address the performance problem.
I've combined the two to avoid creating a span of slow-performance, and to
ease reverting if more problems crop up.
The summary of D61940: This patch removes the "ChangingRegs" facility in
DbgEntityHistoryCalculator, as its overapproximate nature can produce incorrect
variable locations. An unchanging register doesn't mean a variable doesn't
change its location.
The patch kills off everything that calculates the ChangingRegs vector.
Previously ChangingRegs spotted epilogues and marked registers as unchanging if
they weren't modified outside the epilogue, increasing the chance that we can
emit a single-location variable record. Without this feature,
debug-loc-offset.mir and pr19307.mir become temporarily XFAIL. They'll be
re-enabled by D62314, using the FrameDestroy flag to identify epilogues, I've
split this into two steps as FrameDestroy isn't necessarily supported by all
backends.
The logic for terminating variable locations at the end of a basic block now
becomes much more enjoyably simple: we just terminate them all.
Other test changes: inlined-argument.ll becomes XFAIL, but for a longer term.
The current algorithm for detecting that a variable has a single-location
doesn't work in this scenario (inlined function in multiple blocks), only other
bugs were making this test work. fission-ranges.ll gets slightly refreshed too,
as the location of "p" is now correctly determined to be a single location.
Differential Revision: https://reviews.llvm.org/D61940
llvm-svn: 362951
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp | 168 | ||||
-rw-r--r-- | llvm/lib/CodeGen/LiveDebugValues.cpp | 62 |
2 files changed, 113 insertions, 117 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 3bf25eb3619..d87aac94c04 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -224,67 +224,10 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo, clobberRegisterUses(RegVars, I, HistMap, LiveEntries, ClobberingInstr); } -// Returns the first instruction in @MBB which corresponds to -// the function epilogue, or nullptr if @MBB doesn't contain an epilogue. -static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) { - auto LastMI = MBB.getLastNonDebugInstr(); - if (LastMI == MBB.end() || !LastMI->isReturn()) - return nullptr; - // Assume that epilogue starts with instruction having the same debug location - // as the return instruction. - DebugLoc LastLoc = LastMI->getDebugLoc(); - auto Res = LastMI; - for (MachineBasicBlock::const_reverse_iterator I = LastMI.getReverse(), - E = MBB.rend(); - I != E; ++I) { - if (I->getDebugLoc() != LastLoc) - return &*Res; - Res = &*I; - } - // If all instructions have the same debug location, assume whole MBB is - // an epilogue. - return &*MBB.begin(); -} - -// Collect registers that are modified in the function body (their -// contents is changed outside of the prologue and epilogue). -static void collectChangingRegs(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - BitVector &Regs) { - for (const auto &MBB : *MF) { - auto FirstEpilogueInst = getFirstEpilogueInst(MBB); - - for (const auto &MI : MBB) { - // Avoid looking at prologue or epilogue instructions. - if (&MI == FirstEpilogueInst) - break; - if (MI.getFlag(MachineInstr::FrameSetup)) - continue; - - // Look for register defs and register masks. Register masks are - // typically on calls and they clobber everything not in the mask. - for (const MachineOperand &MO : MI.operands()) { - // Skip virtual registers since they are handled by the parent. - if (MO.isReg() && MO.isDef() && MO.getReg() && - !TRI->isVirtualRegister(MO.getReg())) { - for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); - ++AI) - Regs.set(*AI); - } else if (MO.isRegMask()) { - Regs.setBitsNotInMask(MO.getRegMask()); - } - } - } - } -} - void llvm::calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels) { - BitVector ChangingRegs(TRI->getNumRegs()); - collectChangingRegs(MF, TRI, ChangingRegs); - const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); unsigned FrameReg = TRI->getFrameRegister(*MF); @@ -292,43 +235,6 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, DbgValueEntriesMap LiveEntries; for (const auto &MBB : *MF) { for (const auto &MI : MBB) { - if (!MI.isDebugInstr()) { - // Not a DBG_VALUE instruction. It may clobber registers which describe - // some variables. - for (const MachineOperand &MO : MI.operands()) { - if (MO.isReg() && MO.isDef() && MO.getReg()) { - // Ignore call instructions that claim to clobber SP. The AArch64 - // backend does this for aggregate function arguments. - if (MI.isCall() && MO.getReg() == SP) - continue; - // If this is a virtual register, only clobber it since it doesn't - // have aliases. - if (TRI->isVirtualRegister(MO.getReg())) - clobberRegisterUses(RegVars, MO.getReg(), DbgValues, LiveEntries, - MI); - // If this is a register def operand, it may end a debug value - // range. - else { - for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); - ++AI) - if (ChangingRegs.test(*AI)) - clobberRegisterUses(RegVars, *AI, DbgValues, LiveEntries, MI); - } - } else if (MO.isRegMask()) { - // If this is a register mask operand, clobber all debug values in - // non-CSRs. - for (unsigned I : ChangingRegs.set_bits()) { - // Don't consider SP to be clobbered by register masks. - if (unsigned(I) != SP && TRI->isPhysicalRegister(I) && - MO.clobbersPhysReg(I)) { - clobberRegisterUses(RegVars, I, DbgValues, LiveEntries, MI); - } - } - } - } - continue; - } - if (MI.isDebugValue()) { assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!"); // Use the base variable (without any DW_OP_piece expressions) @@ -351,20 +257,72 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt()); DbgLabels.addInstr(L, MI); } - } - // Make sure locations for register-described variables are valid only - // until the end of the basic block (unless it's the last basic block, in - // which case let their liveness run off to the end of the function). + if (MI.isDebugInstr()) + continue; + + // Not a DBG_VALUE instruction. It may clobber registers which describe + // some variables. + for (const MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.isDef() && MO.getReg()) { + // Ignore call instructions that claim to clobber SP. The AArch64 + // backend does this for aggregate function arguments. + if (MI.isCall() && MO.getReg() == SP) + continue; + // If this is a virtual register, only clobber it since it doesn't + // have aliases. + if (TRI->isVirtualRegister(MO.getReg())) + clobberRegisterUses(RegVars, MO.getReg(), DbgValues, LiveEntries, + MI); + // If this is a register def operand, it may end a debug value + // range. Ignore defs of the frame register in the prologue. + else if (MO.getReg() != FrameReg || + !MI.getFlag(MachineInstr::FrameSetup)) { + for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); + ++AI) + clobberRegisterUses(RegVars, *AI, DbgValues, LiveEntries, MI); + } + } else if (MO.isRegMask()) { + // If this is a register mask operand, clobber all debug values in + // non-CSRs. + SmallVector<unsigned, 32> RegsToClobber; + // Don't consider SP to be clobbered by register masks. + for (auto It : RegVars) { + unsigned int Reg = It.first; + if (Reg != SP && TRI->isPhysicalRegister(Reg) && + MO.clobbersPhysReg(Reg)) + RegsToClobber.push_back(Reg); + } + + for (unsigned Reg : RegsToClobber) { + clobberRegisterUses(RegVars, Reg, DbgValues, LiveEntries, MI); + } + } + } // End MO loop. + } // End instr loop. + + // Make sure locations for all variables are valid only until the end of + // the basic block (unless it's the last basic block, in which case let + // their liveness run off to the end of the function). if (!MBB.empty() && &MBB != &MF->back()) { - for (auto I = RegVars.begin(), E = RegVars.end(); I != E;) { - auto CurElem = I++; // CurElem can be erased below. - if (TRI->isVirtualRegister(CurElem->first) || - ChangingRegs.test(CurElem->first) || - CurElem->first == FrameReg) - clobberRegisterUses(RegVars, CurElem, DbgValues, LiveEntries, - MBB.back()); + // Iterate over all variables that have open debug values. + for (auto &Pair : LiveEntries) { + if (Pair.second.empty()) + continue; + + // Create a clobbering entry. + EntryIndex ClobIdx = DbgValues.startClobber(Pair.first, MBB.back()); + + // End all entries. + for (EntryIndex Idx : Pair.second) { + DbgValueHistoryMap::Entry &Ent = DbgValues.getEntry(Pair.first, Idx); + assert(Ent.isDbgValue() && !Ent.isClosed()); + Ent.endEntry(ClobIdx); + } } + + LiveEntries.clear(); + RegVars.clear(); } } } diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp index 8b8a340c179..321984813b6 100644 --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues.cpp @@ -143,7 +143,8 @@ private: enum VarLocKind { InvalidKind = 0, RegisterKind, - SpillLocKind + SpillLocKind, + ImmediateKind } Kind = InvalidKind; /// The value location. Stored separately to avoid repeatedly @@ -152,6 +153,9 @@ private: uint64_t RegNo; SpillLoc SpillLocation; uint64_t Hash; + int64_t Immediate; + const ConstantFP *FPImm; + const ConstantInt *CImm; } Loc; VarLoc(const MachineInstr &MI, LexicalScopes &LS) @@ -164,6 +168,15 @@ private: if (int RegNo = isDbgValueDescribedByReg(MI)) { Kind = RegisterKind; Loc.RegNo = RegNo; + } else if (MI.getOperand(0).isImm()) { + Kind = ImmediateKind; + Loc.Immediate = MI.getOperand(0).getImm(); + } else if (MI.getOperand(0).isFPImm()) { + Kind = ImmediateKind; + Loc.FPImm = MI.getOperand(0).getFPImm(); + } else if (MI.getOperand(0).isCImm()) { + Kind = ImmediateKind; + Loc.CImm = MI.getOperand(0).getCImm(); } } @@ -178,6 +191,9 @@ private: Loc.SpillLocation = {SpillBase, SpillOffset}; } + // Is the Loc field a constant or constant object? + bool isConstant() const { return Kind == ImmediateKind; } + /// If this variable is described by a register, return it, /// otherwise return 0. unsigned isDescribedByReg() const { @@ -195,7 +211,8 @@ private: #endif bool operator==(const VarLoc &Other) const { - return Var == Other.Var && Loc.Hash == Other.Loc.Hash; + return Kind == Other.Kind && Var == Other.Var && + Loc.Hash == Other.Loc.Hash; } /// This operator guarantees that VarLocs are sorted by Variable first. @@ -409,11 +426,23 @@ void LiveDebugValues::transferDebugValue(const MachineInstr &MI, OpenRanges.erase(V); // Add the VarLoc to OpenRanges from this DBG_VALUE. - // TODO: Currently handles DBG_VALUE which has only reg as location. - if (isDbgValueDescribedByReg(MI)) { + unsigned ID; + if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() || + MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) { + // Use normal VarLoc constructor for registers and immediates. VarLoc VL(MI, LS); - unsigned ID = VarLocIDs.insert(VL); + ID = VarLocIDs.insert(VL); + OpenRanges.insert(ID, VL.Var); + } else if (MI.hasOneMemOperand()) { + // It's a stack spill -- fetch spill base and offset. + VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI); + VarLoc VL(MI, SpillLocation.SpillBase, SpillLocation.SpillOffset, LS); + ID = VarLocIDs.insert(VL); OpenRanges.insert(ID, VL.Var); + } else { + // This must be an undefined location. We should leave OpenRanges closed. + assert(MI.getOperand(0).isReg() && MI.getOperand(0).getReg() == 0 && + "Unexpected non-undef DBG_VALUE encountered"); } } @@ -826,13 +855,22 @@ bool LiveDebugValues::join( // a new DBG_VALUE. process() will end this range however appropriate. const VarLoc &DiffIt = VarLocIDs[ID]; const MachineInstr *DebugInstr = &DiffIt.MI; - MachineInstr *MI = BuildMI( - MBB, MBB.instr_begin(), DebugInstr->getDebugLoc(), - DebugInstr->getDesc(), DebugInstr->isIndirectDebugValue(), - DebugInstr->getOperand(0).getReg(), DebugInstr->getDebugVariable(), - DebugInstr->getDebugExpression()); - if (DebugInstr->isIndirectDebugValue()) - MI->getOperand(1).setImm(DebugInstr->getOperand(1).getImm()); + MachineInstr *MI = nullptr; + if (DiffIt.isConstant()) { + MachineOperand MO(DebugInstr->getOperand(0)); + MI = BuildMI(MBB, MBB.instr_begin(), DebugInstr->getDebugLoc(), + DebugInstr->getDesc(), false, MO, + DebugInstr->getDebugVariable(), + DebugInstr->getDebugExpression()); + } else { + MI = BuildMI(MBB, MBB.instr_begin(), DebugInstr->getDebugLoc(), + DebugInstr->getDesc(), DebugInstr->isIndirectDebugValue(), + DebugInstr->getOperand(0).getReg(), + DebugInstr->getDebugVariable(), + DebugInstr->getDebugExpression()); + if (DebugInstr->isIndirectDebugValue()) + MI->getOperand(1).setImm(DebugInstr->getOperand(1).getImm()); + } LLVM_DEBUG(dbgs() << "Inserted: "; MI->dump();); ILS.set(ID); ++NumInserted; |