aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp70
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h63
2 files changed, 104 insertions, 29 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
index a4eb3094612b..cf62b0e5d7e8 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
@@ -544,8 +544,7 @@ public:
// Re-state the variable location: if there's no replacement then NewLoc
// is None and a $noreg DBG_VALUE will be created. Otherwise, a DBG_VALUE
// identifying the alternative location will be emitted.
- const DIExpression *Expr = ActiveVLocIt->second.Properties.DIExpr;
- DbgValueProperties Properties(Expr, false);
+ const DbgValueProperties &Properties = ActiveVLocIt->second.Properties;
PendingDbgValues.push_back(MTracker->emitLoc(NewLoc, Var, Properties));
// Update machine locations <=> variable locations maps. Defer updating
@@ -836,6 +835,15 @@ MachineInstrBuilder MLocTracker::emitLoc(Optional<LocIdx> MLoc,
unsigned Base = Spill.SpillBase;
MIB.addReg(Base);
MIB.addImm(0);
+
+ // Being on the stack makes this location indirect; if it was _already_
+ // indirect though, we need to add extra indirection. See this test for
+ // a scenario where this happens:
+ // llvm/test/DebugInfo/X86/spill-nontrivial-param.ll
+ if (Properties.Indirect) {
+ std::vector<uint64_t> Elts = {dwarf::DW_OP_deref};
+ Expr = DIExpression::append(Expr, Elts);
+ }
} else {
// This is a stack location with a weird subregister offset: emit an undef
// DBG_VALUE instead.
@@ -1288,6 +1296,24 @@ void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
} else if (MI.isMetaInstruction())
return;
+ // We always ignore SP defines on call instructions, they don't actually
+ // change the value of the stack pointer... except for win32's _chkstk. This
+ // is rare: filter quickly for the common case (no stack adjustments, not a
+ // call, etc). If it is a call that modifies SP, recognise the SP register
+ // defs.
+ bool CallChangesSP = false;
+ if (AdjustsStackInCalls && MI.isCall() && MI.getOperand(0).isSymbol() &&
+ !strcmp(MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
+ CallChangesSP = true;
+
+ // Test whether we should ignore a def of this register due to it being part
+ // of the stack pointer.
+ auto IgnoreSPAlias = [this, &MI, CallChangesSP](Register R) -> bool {
+ if (CallChangesSP)
+ return false;
+ return MI.isCall() && MTracker->SPAliases.count(R);
+ };
+
// Find the regs killed by MI, and find regmasks of preserved regs.
// Max out the number of statically allocated elements in `DeadRegs`, as this
// prevents fallback to std::set::count() operations.
@@ -1298,7 +1324,7 @@ void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
// Determine whether the operand is a register def.
if (MO.isReg() && MO.isDef() && MO.getReg() &&
Register::isPhysicalRegister(MO.getReg()) &&
- !(MI.isCall() && MTracker->SPAliases.count(MO.getReg()))) {
+ !IgnoreSPAlias(MO.getReg())) {
// Remove ranges of all aliased registers.
for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
// FIXME: Can we break out of this loop early if no insertion occurs?
@@ -1347,6 +1373,9 @@ void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
continue;
Register Reg = MTracker->LocIdxToLocID[L.Idx];
+ if (IgnoreSPAlias(Reg))
+ continue;
+
for (auto *MO : RegMaskPtrs)
if (MO->clobbersPhysReg(Reg))
TTracker->clobberMloc(L.Idx, MI.getIterator(), false);
@@ -1628,9 +1657,10 @@ bool InstrRefBasedLDV::transferRegisterCopy(MachineInstr &MI) {
/// fragments of that DILocalVariable which overlap. This reduces work during
/// the data-flow stage from "Find any overlapping fragments" to "Check if the
/// known-to-overlap fragments are present".
-/// \param MI A previously unprocessed DEBUG_VALUE instruction to analyze for
+/// \param MI A previously unprocessed debug instruction to analyze for
/// fragment usage.
void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) {
+ assert(MI.isDebugValue() || MI.isDebugRef());
DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(),
MI.getDebugLoc()->getInlinedAt());
FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
@@ -1732,7 +1762,7 @@ void InstrRefBasedLDV::produceMLocTransferFunction(
for (auto &MI : MBB) {
process(MI);
// Also accumulate fragment map.
- if (MI.isDebugValue())
+ if (MI.isDebugValue() || MI.isDebugRef())
accumulateFragmentMap(MI);
// Create a map from the instruction number (if present) to the
@@ -2322,15 +2352,8 @@ Optional<ValueIDNum> InstrRefBasedLDV::pickVPHILoc(
bool InstrRefBasedLDV::vlocJoin(
MachineBasicBlock &MBB, LiveIdxT &VLOCOutLocs,
- SmallPtrSet<const MachineBasicBlock *, 8> &InScopeBlocks,
SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore,
DbgValue &LiveIn) {
- // To emulate VarLocBasedImpl, process this block if it's not in scope but
- // _does_ assign a variable value. No live-ins for this scope are transferred
- // in though, so we can return immediately.
- if (InScopeBlocks.count(&MBB) == 0 && !ArtificialBlocks.count(&MBB))
- return false;
-
LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n");
bool Changed = false;
@@ -2466,11 +2489,10 @@ void InstrRefBasedLDV::buildVLocValueMap(const DILocation *DILoc,
// "blocks that are potentially in scope. See comment at start of vlocJoin.
SmallPtrSet<const MachineBasicBlock *, 8> InScopeBlocks = BlocksToExplore;
- // Old LiveDebugValues tracks variable locations that come out of blocks
- // not in scope, where DBG_VALUEs occur. This is something we could
- // legitimately ignore, but lets allow it for now.
- if (EmulateOldLDV)
- BlocksToExplore.insert(AssignBlocks.begin(), AssignBlocks.end());
+ // VarLoc LiveDebugValues tracks variable locations that are defined in
+ // blocks not in scope. This is something we could legitimately ignore, but
+ // lets allow it for now for the sake of coverage.
+ BlocksToExplore.insert(AssignBlocks.begin(), AssignBlocks.end());
// We also need to propagate variable values through any artificial blocks
// that immediately follow blocks in scope.
@@ -2635,7 +2657,7 @@ void InstrRefBasedLDV::buildVLocValueMap(const DILocation *DILoc,
// Join values from predecessors. Updates LiveInIdx, and writes output
// into JoinedInLocs.
bool InLocsChanged =
- vlocJoin(*MBB, LiveOutIdx, InScopeBlocks, BlocksToExplore, *LiveIn);
+ vlocJoin(*MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
SmallVector<const MachineBasicBlock *, 8> Preds;
for (const auto *Pred : MBB->predecessors())
@@ -2730,6 +2752,8 @@ void InstrRefBasedLDV::buildVLocValueMap(const DILocation *DILoc,
continue;
if (BlockLiveIn->Kind == DbgValue::VPHI)
BlockLiveIn->Kind = DbgValue::Def;
+ assert(BlockLiveIn->Properties.DIExpr->getFragmentInfo() ==
+ Var.getFragment() && "Fragment info missing during value prop");
Output[MBB->getNumber()].push_back(std::make_pair(Var, *BlockLiveIn));
}
} // Per-variable loop.
@@ -2879,6 +2903,12 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
MFI = &MF.getFrameInfo();
LS.initialize(MF);
+ const auto &STI = MF.getSubtarget();
+ AdjustsStackInCalls = MFI->adjustsStack() &&
+ STI.getFrameLowering()->stackProbeFunctionModifiesSP();
+ if (AdjustsStackInCalls)
+ StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
+
MTracker =
new MLocTracker(MF, *TII, *TRI, *MF.getSubtarget().getTargetLowering());
VTracker = nullptr;
@@ -2895,7 +2925,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
++MaxNumBlocks;
MLocTransfer.resize(MaxNumBlocks);
- vlocs.resize(MaxNumBlocks);
+ vlocs.resize(MaxNumBlocks, VLocTracker(OverlapFragments, EmptyExpr));
SavedLiveIns.resize(MaxNumBlocks);
initialSetup(MF);
@@ -3040,6 +3070,8 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
BBNumToRPO.clear();
DebugInstrNumToInstr.clear();
DebugPHINumToValue.clear();
+ OverlapFragments.clear();
+ SeenFragments.clear();
return Changed;
}
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h
index d96ef6d4f6e5..789205e61cdb 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h
+++ b/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h
@@ -655,6 +655,14 @@ public:
const DbgValueProperties &Properties);
};
+/// Types for recording sets of variable fragments that overlap. For a given
+/// local variable, we record all other fragments of that variable that could
+/// overlap it, to reduce search time.
+using FragmentOfVar =
+ std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
+using OverlapMap =
+ DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;
+
/// Collection of DBG_VALUEs observed when traversing a block. Records each
/// variable and the value the DBG_VALUE refers to. Requires the machine value
/// location dataflow algorithm to have run already, so that values can be
@@ -672,9 +680,12 @@ public:
MapVector<DebugVariable, DbgValue> Vars;
DenseMap<DebugVariable, const DILocation *> Scopes;
MachineBasicBlock *MBB = nullptr;
+ const OverlapMap &OverlappingFragments;
+ DbgValueProperties EmptyProperties;
public:
- VLocTracker() {}
+ VLocTracker(const OverlapMap &O, const DIExpression *EmptyExpr)
+ : OverlappingFragments(O), EmptyProperties(EmptyExpr, false) {}
void defVar(const MachineInstr &MI, const DbgValueProperties &Properties,
Optional<ValueIDNum> ID) {
@@ -689,6 +700,8 @@ public:
if (!Result.second)
Result.first->second = Rec;
Scopes[Var] = MI.getDebugLoc().get();
+
+ considerOverlaps(Var, MI.getDebugLoc().get());
}
void defVar(const MachineInstr &MI, const MachineOperand &MO) {
@@ -704,16 +717,37 @@ public:
if (!Result.second)
Result.first->second = Rec;
Scopes[Var] = MI.getDebugLoc().get();
+
+ considerOverlaps(Var, MI.getDebugLoc().get());
}
-};
-/// Types for recording sets of variable fragments that overlap. For a given
-/// local variable, we record all other fragments of that variable that could
-/// overlap it, to reduce search time.
-using FragmentOfVar =
- std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
-using OverlapMap =
- DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;
+ void considerOverlaps(const DebugVariable &Var, const DILocation *Loc) {
+ auto Overlaps = OverlappingFragments.find(
+ {Var.getVariable(), Var.getFragmentOrDefault()});
+ if (Overlaps == OverlappingFragments.end())
+ return;
+
+ // Otherwise: terminate any overlapped variable locations.
+ for (auto FragmentInfo : Overlaps->second) {
+ // The "empty" fragment is stored as DebugVariable::DefaultFragment, so
+ // that it overlaps with everything, however its cannonical representation
+ // in a DebugVariable is as "None".
+ Optional<DIExpression::FragmentInfo> OptFragmentInfo = FragmentInfo;
+ if (DebugVariable::isDefaultFragment(FragmentInfo))
+ OptFragmentInfo = None;
+
+ DebugVariable Overlapped(Var.getVariable(), OptFragmentInfo,
+ Var.getInlinedAt());
+ DbgValue Rec = DbgValue(EmptyProperties, DbgValue::Undef);
+
+ // Attempt insertion; overwrite if it's already mapped.
+ auto Result = Vars.insert(std::make_pair(Overlapped, Rec));
+ if (!Result.second)
+ Result.first->second = Rec;
+ Scopes[Overlapped] = Loc;
+ }
+ }
+};
// XXX XXX docs
class InstrRefBasedLDV : public LDVImpl {
@@ -817,6 +851,16 @@ private:
OverlapMap OverlapFragments;
VarToFragments SeenFragments;
+ /// True if we need to examine call instructions for stack clobbers. We
+ /// normally assume that they don't clobber SP, but stack probes on Windows
+ /// do.
+ bool AdjustsStackInCalls = false;
+
+ /// If AdjustsStackInCalls is true, this holds the name of the target's stack
+ /// probe function, which is the function we expect will alter the stack
+ /// pointer.
+ StringRef StackProbeSymbolName;
+
/// Tests whether this instruction is a spill to a stack slot.
bool isSpillInstruction(const MachineInstr &MI, MachineFunction *MF);
@@ -962,7 +1006,6 @@ private:
/// \returns true if any live-ins change value, either from value propagation
/// or PHI elimination.
bool vlocJoin(MachineBasicBlock &MBB, LiveIdxT &VLOCOutLocs,
- SmallPtrSet<const MachineBasicBlock *, 8> &InScopeBlocks,
SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore,
DbgValue &LiveIn);