diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/CodeGen/LiveDebugVariables.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) |
Notes
Diffstat (limited to 'lib/CodeGen/LiveDebugVariables.cpp')
-rw-r--r-- | lib/CodeGen/LiveDebugVariables.cpp | 227 |
1 files changed, 137 insertions, 90 deletions
diff --git a/lib/CodeGen/LiveDebugVariables.cpp b/lib/CodeGen/LiveDebugVariables.cpp index 3ff03ec4a7ee..d0d889782a35 100644 --- a/lib/CodeGen/LiveDebugVariables.cpp +++ b/lib/CodeGen/LiveDebugVariables.cpp @@ -132,14 +132,18 @@ private: unsigned WasIndirect : 1; }; -/// LocMap - Map of where a user value is live, and its location. +/// Map of where a user value is live, and its location. using LocMap = IntervalMap<SlotIndex, DbgValueLocation, 4>; +/// Map of stack slot offsets for spilled locations. +/// Non-spilled locations are not added to the map. +using SpillOffsetMap = DenseMap<unsigned, unsigned>; + namespace { class LDVImpl; -/// UserValue - A user value is a part of a debug info user variable. +/// A user value is a part of a debug info user variable. /// /// A DBG_VALUE instruction notes that (a sub-register of) a virtual register /// holds part of a user variable. The part is identified by a byte offset. @@ -166,26 +170,26 @@ class UserValue { /// lexical scope. SmallSet<SlotIndex, 2> trimmedDefs; - /// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo. + /// Insert a DBG_VALUE into MBB at Idx for LocNo. void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, - SlotIndex StopIdx, - DbgValueLocation Loc, bool Spilled, LiveIntervals &LIS, + SlotIndex StopIdx, DbgValueLocation Loc, bool Spilled, + unsigned SpillOffset, LiveIntervals &LIS, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI); - /// splitLocation - Replace OldLocNo ranges with NewRegs ranges where NewRegs + /// Replace OldLocNo ranges with NewRegs ranges where NewRegs /// is live. Returns true if any changes were made. bool splitLocation(unsigned OldLocNo, ArrayRef<unsigned> NewRegs, LiveIntervals &LIS); public: - /// UserValue - Create a new UserValue. + /// Create a new UserValue. UserValue(const DILocalVariable *var, const DIExpression *expr, DebugLoc L, LocMap::Allocator &alloc) : Variable(var), Expression(expr), dl(std::move(L)), leader(this), locInts(alloc) {} - /// getLeader - Get the leader of this value's equivalence class. + /// Get the leader of this value's equivalence class. UserValue *getLeader() { UserValue *l = leader; while (l != l->leader) @@ -193,10 +197,10 @@ public: return leader = l; } - /// getNext - Return the next UserValue in the equivalence class. + /// Return the next UserValue in the equivalence class. UserValue *getNext() const { return next; } - /// match - Does this UserValue match the parameters? + /// Does this UserValue match the parameters? bool match(const DILocalVariable *Var, const DIExpression *Expr, const DILocation *IA) const { // FIXME: The fragment should be part of the equivalence class, but not @@ -204,7 +208,7 @@ public: return Var == Variable && Expr == Expression && dl->getInlinedAt() == IA; } - /// merge - Merge equivalence classes. + /// Merge equivalence classes. static UserValue *merge(UserValue *L1, UserValue *L2) { L2 = L2->getLeader(); if (!L1) @@ -256,10 +260,10 @@ public: return locations.size() - 1; } - /// mapVirtRegs - Ensure that all virtual register locations are mapped. + /// Ensure that all virtual register locations are mapped. void mapVirtRegs(LDVImpl *LDV); - /// addDef - Add a definition point to this value. + /// Add a definition point to this value. void addDef(SlotIndex Idx, const MachineOperand &LocMO, bool IsIndirect) { DbgValueLocation Loc(getLocationNo(LocMO), IsIndirect); // Add a singular (Idx,Idx) -> Loc mapping. @@ -271,63 +275,71 @@ public: I.setValue(Loc); } - /// extendDef - Extend the current definition as far as possible down. + /// Extend the current definition as far as possible down. + /// /// Stop when meeting an existing def or when leaving the live - /// range of VNI. - /// End points where VNI is no longer live are added to Kills. - /// @param Idx Starting point for the definition. - /// @param Loc Location number to propagate. - /// @param LR Restrict liveness to where LR has the value VNI. May be null. - /// @param VNI When LR is not null, this is the value to restrict to. - /// @param Kills Append end points of VNI's live range to Kills. - /// @param LIS Live intervals analysis. + /// range of VNI. End points where VNI is no longer live are added to Kills. + /// + /// We only propagate DBG_VALUES locally here. LiveDebugValues performs a + /// data-flow analysis to propagate them beyond basic block boundaries. + /// + /// \param Idx Starting point for the definition. + /// \param Loc Location number to propagate. + /// \param LR Restrict liveness to where LR has the value VNI. May be null. + /// \param VNI When LR is not null, this is the value to restrict to. + /// \param [out] Kills Append end points of VNI's live range to Kills. + /// \param LIS Live intervals analysis. void extendDef(SlotIndex Idx, DbgValueLocation Loc, LiveRange *LR, const VNInfo *VNI, SmallVectorImpl<SlotIndex> *Kills, LiveIntervals &LIS); - /// addDefsFromCopies - The value in LI/LocNo may be copies to other - /// registers. Determine if any of the copies are available at the kill - /// points, and add defs if possible. - /// @param LI Scan for copies of the value in LI->reg. - /// @param LocNo Location number of LI->reg. - /// @param WasIndirect Indicates if the original use of LI->reg was indirect - /// @param Kills Points where the range of LocNo could be extended. - /// @param NewDefs Append (Idx, LocNo) of inserted defs here. + /// The value in LI/LocNo may be copies to other registers. Determine if + /// any of the copies are available at the kill points, and add defs if + /// possible. + /// + /// \param LI Scan for copies of the value in LI->reg. + /// \param LocNo Location number of LI->reg. + /// \param WasIndirect Indicates if the original use of LI->reg was indirect + /// \param Kills Points where the range of LocNo could be extended. + /// \param [in,out] NewDefs Append (Idx, LocNo) of inserted defs here. void addDefsFromCopies( LiveInterval *LI, unsigned LocNo, bool WasIndirect, const SmallVectorImpl<SlotIndex> &Kills, SmallVectorImpl<std::pair<SlotIndex, DbgValueLocation>> &NewDefs, MachineRegisterInfo &MRI, LiveIntervals &LIS); - /// computeIntervals - Compute the live intervals of all locations after - /// collecting all their def points. + /// Compute the live intervals of all locations after collecting all their + /// def points. void computeIntervals(MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, LiveIntervals &LIS, LexicalScopes &LS); - /// splitRegister - Replace OldReg ranges with NewRegs ranges where NewRegs is + /// Replace OldReg ranges with NewRegs ranges where NewRegs is /// live. Returns true if any changes were made. bool splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs, LiveIntervals &LIS); - /// rewriteLocations - Rewrite virtual register locations according to the - /// provided virtual register map. Record which locations were spilled. - void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI, - BitVector &SpilledLocations); + /// Rewrite virtual register locations according to the provided virtual + /// register map. Record the stack slot offsets for the locations that + /// were spilled. + void rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF, + const TargetInstrInfo &TII, + const TargetRegisterInfo &TRI, + SpillOffsetMap &SpillOffsets); - /// emitDebugValues - Recreate DBG_VALUE instruction from data structures. + /// Recreate DBG_VALUE instruction from data structures. void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, - const BitVector &SpilledLocations); + const SpillOffsetMap &SpillOffsets); - /// getDebugLoc - Return DebugLoc of this UserValue. + /// Return DebugLoc of this UserValue. DebugLoc getDebugLoc() { return dl;} void print(raw_ostream &, const TargetRegisterInfo *); }; -/// LDVImpl - Implementation of the LiveDebugVariables pass. +/// Implementation of the LiveDebugVariables pass. class LDVImpl { LiveDebugVariables &pass; LocMap::Allocator allocator; @@ -341,7 +353,7 @@ class LDVImpl { /// Whether the machine function is modified during the pass. bool ModifiedMF = false; - /// userValues - All allocated UserValue instances. + /// All allocated UserValue instances. SmallVector<std::unique_ptr<UserValue>, 8> userValues; /// Map virtual register to eq class leader. @@ -352,27 +364,31 @@ class LDVImpl { using UVMap = DenseMap<const DILocalVariable *, UserValue *>; UVMap userVarMap; - /// getUserValue - Find or create a UserValue. + /// Find or create a UserValue. UserValue *getUserValue(const DILocalVariable *Var, const DIExpression *Expr, const DebugLoc &DL); - /// lookupVirtReg - Find the EC leader for VirtReg or null. + /// Find the EC leader for VirtReg or null. UserValue *lookupVirtReg(unsigned VirtReg); - /// handleDebugValue - Add DBG_VALUE instruction to our maps. - /// @param MI DBG_VALUE instruction - /// @param Idx Last valid SLotIndex before instruction. - /// @return True if the DBG_VALUE instruction should be deleted. + /// Add DBG_VALUE instruction to our maps. + /// + /// \param MI DBG_VALUE instruction + /// \param Idx Last valid SLotIndex before instruction. + /// + /// \returns True if the DBG_VALUE instruction should be deleted. bool handleDebugValue(MachineInstr &MI, SlotIndex Idx); - /// collectDebugValues - Collect and erase all DBG_VALUE instructions, adding - /// a UserValue def for each instruction. - /// @param mf MachineFunction to be scanned. - /// @return True if any debug values were found. + /// Collect and erase all DBG_VALUE instructions, adding a UserValue def + /// for each instruction. + /// + /// \param mf MachineFunction to be scanned. + /// + /// \returns True if any debug values were found. bool collectDebugValues(MachineFunction &mf); - /// computeIntervals - Compute the live intervals of all user values after - /// collecting all their def points. + /// Compute the live intervals of all user values after collecting all + /// their def points. void computeIntervals(); public: @@ -380,7 +396,7 @@ public: bool runOnMachineFunction(MachineFunction &mf); - /// clear - Release all memory. + /// Release all memory. void clear() { MF = nullptr; userValues.clear(); @@ -393,13 +409,13 @@ public: ModifiedMF = false; } - /// mapVirtReg - Map virtual register to an equivalence class. + /// Map virtual register to an equivalence class. void mapVirtReg(unsigned VirtReg, UserValue *EC); - /// splitRegister - Replace all references to OldReg with NewRegs. + /// Replace all references to OldReg with NewRegs. void splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs); - /// emitDebugValues - Recreate DBG_VALUE instruction from data structures. + /// Recreate DBG_VALUE instruction from data structures. void emitDebugValues(VirtRegMap *VRM); void print(raw_ostream&); @@ -578,30 +594,33 @@ bool LDVImpl::collectDebugValues(MachineFunction &mf) { MachineBasicBlock *MBB = &*MFI; for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); MBBI != MBBE;) { - if (!MBBI->isDebugValue()) { + // Use the first debug instruction in the sequence to get a SlotIndex + // for following consecutive debug instructions. + if (!MBBI->isDebugInstr()) { ++MBBI; continue; } - // DBG_VALUE has no slot index, use the previous instruction instead. + // Debug instructions has no slot index. Use the previous + // non-debug instruction's SlotIndex as its SlotIndex. SlotIndex Idx = MBBI == MBB->begin() ? LIS->getMBBStartIdx(MBB) : LIS->getInstructionIndex(*std::prev(MBBI)).getRegSlot(); - // Handle consecutive DBG_VALUE instructions with the same slot index. + // Handle consecutive debug instructions with the same slot index. do { - if (handleDebugValue(*MBBI, Idx)) { + // Only handle DBG_VALUE in handleDebugValue(). Skip all other + // kinds of debug instructions. + if (MBBI->isDebugValue() && handleDebugValue(*MBBI, Idx)) { MBBI = MBB->erase(MBBI); Changed = true; } else ++MBBI; - } while (MBBI != MBBE && MBBI->isDebugValue()); + } while (MBBI != MBBE && MBBI->isDebugInstr()); } } return Changed; } -/// We only propagate DBG_VALUES locally here. LiveDebugValues performs a -/// data-flow analysis to propagate them beyond basic block boundaries. void UserValue::extendDef(SlotIndex Idx, DbgValueLocation Loc, LiveRange *LR, const VNInfo *VNI, SmallVectorImpl<SlotIndex> *Kills, LiveIntervals &LIS) { @@ -752,7 +771,15 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI, } SmallVector<SlotIndex, 16> Kills; extendDef(Idx, Loc, LI, VNI, &Kills, LIS); - if (LI) + // FIXME: Handle sub-registers in addDefsFromCopies. The problem is that + // if the original location for example is %vreg0:sub_hi, and we find a + // full register copy in addDefsFromCopies (at the moment it only handles + // full register copies), then we must add the sub1 sub-register index to + // the new location. However, that is only possible if the new virtual + // register is of the same regclass (or if there is an equivalent + // sub-register in that regclass). For now, simply skip handling copies if + // a sub-register is involved. + if (LI && !LocMO.getSubReg()) addDefsFromCopies(LI, Loc.locNo(), Loc.wasIndirect(), Kills, Defs, MRI, LIS); continue; @@ -1039,8 +1066,10 @@ splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs, LiveIntervals &LIS) { static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs); } -void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI, - BitVector &SpilledLocations) { +void UserValue::rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF, + const TargetInstrInfo &TII, + const TargetRegisterInfo &TRI, + SpillOffsetMap &SpillOffsets) { // Build a set of new locations with new numbers so we can coalesce our // IntervalMap if two vreg intervals collapse to the same physical location. // Use MapVector instead of SetVector because MapVector::insert returns the @@ -1049,10 +1078,11 @@ void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI, // FIXME: This will be problematic if we ever support direct and indirect // frame index locations, i.e. expressing both variables in memory and // 'int x, *px = &x'. The "spilled" bit must become part of the location. - MapVector<MachineOperand, bool> NewLocations; + MapVector<MachineOperand, std::pair<bool, unsigned>> NewLocations; SmallVector<unsigned, 4> LocNoMap(locations.size()); for (unsigned I = 0, E = locations.size(); I != E; ++I) { bool Spilled = false; + unsigned SpillOffset = 0; MachineOperand Loc = locations[I]; // Only virtual registers are rewritten. if (Loc.isReg() && Loc.getReg() && @@ -1065,7 +1095,16 @@ void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI, // non-existent sub-register, and %noreg is exactly what we want. Loc.substPhysReg(VRM.getPhys(VirtReg), TRI); } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) { - // FIXME: Translate SubIdx to a stackslot offset. + // Retrieve the stack slot offset. + unsigned SpillSize; + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterClass *TRC = MRI.getRegClass(VirtReg); + bool Success = TII.getStackSlotRange(TRC, Loc.getSubReg(), SpillSize, + SpillOffset, MF); + + // FIXME: Invalidate the location if the offset couldn't be calculated. + (void)Success; + Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg)); Spilled = true; } else { @@ -1076,20 +1115,22 @@ void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI, // Insert this location if it doesn't already exist and record a mapping // from the old number to the new number. - auto InsertResult = NewLocations.insert({Loc, Spilled}); + auto InsertResult = NewLocations.insert({Loc, {Spilled, SpillOffset}}); unsigned NewLocNo = std::distance(NewLocations.begin(), InsertResult.first); LocNoMap[I] = NewLocNo; } - // Rewrite the locations and record which ones were spill slots. + // Rewrite the locations and record the stack slot offsets for spills. locations.clear(); - SpilledLocations.clear(); - SpilledLocations.resize(NewLocations.size()); + SpillOffsets.clear(); for (auto &Pair : NewLocations) { + bool Spilled; + unsigned SpillOffset; + std::tie(Spilled, SpillOffset) = Pair.second; locations.push_back(Pair.first); - if (Pair.second) { + if (Spilled) { unsigned NewLocNo = std::distance(&*NewLocations.begin(), &Pair); - SpilledLocations.set(NewLocNo); + SpillOffsets[NewLocNo] = SpillOffset; } } @@ -1158,10 +1199,9 @@ findNextInsertLocation(MachineBasicBlock *MBB, } void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, - SlotIndex StopIdx, - DbgValueLocation Loc, bool Spilled, - LiveIntervals &LIS, - const TargetInstrInfo &TII, + SlotIndex StopIdx, DbgValueLocation Loc, + bool Spilled, unsigned SpillOffset, + LiveIntervals &LIS, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI) { SlotIndex MBBEndIdx = LIS.getMBBEndIdx(&*MBB); // Only search within the current MBB. @@ -1184,12 +1224,14 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, // If the location was spilled, the new DBG_VALUE will be indirect. If the // original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate - // that the original virtual register was a pointer. + // that the original virtual register was a pointer. Also, add the stack slot + // offset for the spilled register to the expression. const DIExpression *Expr = Expression; bool IsIndirect = Loc.wasIndirect(); if (Spilled) { - if (IsIndirect) - Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); + auto Deref = IsIndirect ? DIExpression::WithDeref : DIExpression::NoDeref; + Expr = + DIExpression::prepend(Expr, DIExpression::NoDeref, SpillOffset, Deref); IsIndirect = true; } @@ -1208,14 +1250,17 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, - const BitVector &SpilledLocations) { + const SpillOffsetMap &SpillOffsets) { MachineFunction::iterator MFEnd = VRM->getMachineFunction().end(); for (LocMap::const_iterator I = locInts.begin(); I.valid();) { SlotIndex Start = I.start(); SlotIndex Stop = I.stop(); DbgValueLocation Loc = I.value(); - bool Spilled = !Loc.isUndef() ? SpilledLocations.test(Loc.locNo()) : false; + auto SpillIt = + !Loc.isUndef() ? SpillOffsets.find(Loc.locNo()) : SpillOffsets.end(); + bool Spilled = SpillIt != SpillOffsets.end(); + unsigned SpillOffset = Spilled ? SpillIt->second : 0; // If the interval start was trimmed to the lexical scope insert the // DBG_VALUE at the previous index (otherwise it appears after the @@ -1228,7 +1273,8 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB); LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB) << '-' << MBBEnd); - insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, LIS, TII, TRI); + insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, SpillOffset, LIS, TII, + TRI); // This interval may span multiple basic blocks. // Insert a DBG_VALUE into each one. while (Stop > MBBEnd) { @@ -1238,7 +1284,8 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, break; MBBEnd = LIS.getMBBEndIdx(&*MBB); LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB) << '-' << MBBEnd); - insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, LIS, TII, TRI); + insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, SpillOffset, LIS, TII, + TRI); } LLVM_DEBUG(dbgs() << '\n'); if (MBB == MFEnd) @@ -1253,11 +1300,11 @@ void LDVImpl::emitDebugValues(VirtRegMap *VRM) { if (!MF) return; const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); - BitVector SpilledLocations; + SpillOffsetMap SpillOffsets; for (unsigned i = 0, e = userValues.size(); i != e; ++i) { LLVM_DEBUG(userValues[i]->print(dbgs(), TRI)); - userValues[i]->rewriteLocations(*VRM, *TRI, SpilledLocations); - userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpilledLocations); + userValues[i]->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets); + userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets); } EmitDone = true; } |