summaryrefslogtreecommitdiff
path: root/lib/CodeGen/LiveDebugVariables.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/CodeGen/LiveDebugVariables.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/CodeGen/LiveDebugVariables.cpp')
-rw-r--r--lib/CodeGen/LiveDebugVariables.cpp227
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;
}