Skip to content

Commit 84ca706

Browse files
committed
[DebugInfo][NFCI] Split salvageDebugInfo into helper functions
Some use cases are appearing where salvaging is needed that does not correspond to an instruction being deleted -- for example an instruction being sunk, or a Value not being available in a block being isel'd. Enable more fine grained control over how salavging occurs by splitting the logic into helper functions, separating things that are specific to working on DbgVariableIntrinsics from those specific to interpreting IR and building DIExpressions. Differential Revision: https://reviews.llvm.org/D57696 llvm-svn: 353156
1 parent 7279895 commit 84ca706

File tree

2 files changed

+94
-82
lines changed

2 files changed

+94
-82
lines changed

llvm/include/llvm/Transforms/Utils/Local.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,18 @@ void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
341341
/// Returns true if any debug users were updated.
342342
bool salvageDebugInfo(Instruction &I);
343343

344+
/// Implementation of salvageDebugInfo, applying only to instructions in
345+
/// \p Insns, rather than all debug users of \p I.
346+
bool salvageDebugInfoForDbgValues(Instruction &I,
347+
ArrayRef<DbgVariableIntrinsic *> Insns);
348+
349+
/// Given an instruction \p I and DIExpression \p DIExpr operating on it, write
350+
/// the effects of \p I into the returned DIExpression, or return nullptr if
351+
/// it cannot be salvaged. \p StackVal: whether DW_OP_stack_value should be
352+
/// appended to the expression.
353+
DIExpression *salvageDebugInfoImpl(Instruction &I, DIExpression *DIExpr,
354+
bool StackVal);
355+
344356
/// Point debug users of \p From to \p To or salvage them. Use this function
345357
/// only when replacing all uses of \p From with \p To, with a guarantee that
346358
/// \p From is going to be deleted.

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,120 +1593,120 @@ bool llvm::salvageDebugInfo(Instruction &I) {
15931593
if (DbgUsers.empty())
15941594
return false;
15951595

1596-
auto &M = *I.getModule();
1597-
auto &DL = M.getDataLayout();
1596+
return salvageDebugInfoForDbgValues(I, DbgUsers);
1597+
}
1598+
1599+
bool llvm::salvageDebugInfoForDbgValues(
1600+
Instruction &I, ArrayRef<DbgVariableIntrinsic *> DbgUsers) {
15981601
auto &Ctx = I.getContext();
15991602
auto wrapMD = [&](Value *V) { return wrapValueInMetadata(Ctx, V); };
16001603

1601-
auto doSalvage = [&](DbgVariableIntrinsic *DII, SmallVectorImpl<uint64_t> &Ops) {
1602-
auto *DIExpr = DII->getExpression();
1603-
if (!Ops.empty()) {
1604-
// Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they
1605-
// are implicitly pointing out the value as a DWARF memory location
1606-
// description.
1607-
bool WithStackValue = isa<DbgValueInst>(DII);
1608-
DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue);
1609-
}
1604+
for (auto *DII : DbgUsers) {
1605+
// Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they
1606+
// are implicitly pointing out the value as a DWARF memory location
1607+
// description.
1608+
bool StackValue = isa<DbgValueInst>(DII);
1609+
1610+
DIExpression *DIExpr =
1611+
salvageDebugInfoImpl(I, DII->getExpression(), StackValue);
1612+
1613+
// salvageDebugInfoImpl should fail on examining the first element of
1614+
// DbgUsers, or none of them.
1615+
if (!DIExpr)
1616+
return false;
1617+
16101618
DII->setOperand(0, wrapMD(I.getOperand(0)));
16111619
DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr));
16121620
LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');
1621+
}
1622+
1623+
return true;
1624+
}
1625+
1626+
DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,
1627+
DIExpression *SrcDIExpr,
1628+
bool WithStackValue) {
1629+
auto &M = *I.getModule();
1630+
auto &DL = M.getDataLayout();
1631+
1632+
// Apply a vector of opcodes to the source DIExpression.
1633+
auto doSalvage = [&](SmallVectorImpl<uint64_t> &Ops) -> DIExpression * {
1634+
DIExpression *DIExpr = SrcDIExpr;
1635+
if (!Ops.empty()) {
1636+
DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue);
1637+
}
1638+
return DIExpr;
16131639
};
16141640

1615-
auto applyOffset = [&](DbgVariableIntrinsic *DII, uint64_t Offset) {
1641+
// Apply the given offset to the source DIExpression.
1642+
auto applyOffset = [&](uint64_t Offset) -> DIExpression * {
16161643
SmallVector<uint64_t, 8> Ops;
16171644
DIExpression::appendOffset(Ops, Offset);
1618-
doSalvage(DII, Ops);
1645+
return doSalvage(Ops);
16191646
};
16201647

1621-
auto applyOps = [&](DbgVariableIntrinsic *DII,
1622-
std::initializer_list<uint64_t> Opcodes) {
1648+
// initializer-list helper for applying operators to the source DIExpression.
1649+
auto applyOps =
1650+
[&](std::initializer_list<uint64_t> Opcodes) -> DIExpression * {
16231651
SmallVector<uint64_t, 8> Ops(Opcodes);
1624-
doSalvage(DII, Ops);
1652+
return doSalvage(Ops);
16251653
};
16261654

16271655
if (auto *CI = dyn_cast<CastInst>(&I)) {
16281656
if (!CI->isNoopCast(DL))
1629-
return false;
1657+
return nullptr;
16301658

16311659
// No-op casts are irrelevant for debug info.
1632-
MetadataAsValue *CastSrc = wrapMD(I.getOperand(0));
1633-
for (auto *DII : DbgUsers) {
1634-
DII->setOperand(0, CastSrc);
1635-
LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');
1636-
}
1637-
return true;
1660+
return SrcDIExpr;
16381661
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
16391662
unsigned BitWidth =
16401663
M.getDataLayout().getIndexSizeInBits(GEP->getPointerAddressSpace());
1641-
// Rewrite a constant GEP into a DIExpression. Since we are performing
1642-
// arithmetic to compute the variable's *value* in the DIExpression, we
1643-
// need to mark the expression with a DW_OP_stack_value.
1664+
// Rewrite a constant GEP into a DIExpression.
16441665
APInt Offset(BitWidth, 0);
1645-
if (GEP->accumulateConstantOffset(M.getDataLayout(), Offset))
1646-
for (auto *DII : DbgUsers)
1647-
applyOffset(DII, Offset.getSExtValue());
1648-
return true;
1666+
if (GEP->accumulateConstantOffset(M.getDataLayout(), Offset)) {
1667+
return applyOffset(Offset.getSExtValue());
1668+
} else {
1669+
return nullptr;
1670+
}
16491671
} else if (auto *BI = dyn_cast<BinaryOperator>(&I)) {
16501672
// Rewrite binary operations with constant integer operands.
16511673
auto *ConstInt = dyn_cast<ConstantInt>(I.getOperand(1));
16521674
if (!ConstInt || ConstInt->getBitWidth() > 64)
1653-
return false;
1675+
return nullptr;
16541676

16551677
uint64_t Val = ConstInt->getSExtValue();
1656-
for (auto *DII : DbgUsers) {
1657-
switch (BI->getOpcode()) {
1658-
case Instruction::Add:
1659-
applyOffset(DII, Val);
1660-
break;
1661-
case Instruction::Sub:
1662-
applyOffset(DII, -int64_t(Val));
1663-
break;
1664-
case Instruction::Mul:
1665-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_mul});
1666-
break;
1667-
case Instruction::SDiv:
1668-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_div});
1669-
break;
1670-
case Instruction::SRem:
1671-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_mod});
1672-
break;
1673-
case Instruction::Or:
1674-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_or});
1675-
break;
1676-
case Instruction::And:
1677-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_and});
1678-
break;
1679-
case Instruction::Xor:
1680-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_xor});
1681-
break;
1682-
case Instruction::Shl:
1683-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_shl});
1684-
break;
1685-
case Instruction::LShr:
1686-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_shr});
1687-
break;
1688-
case Instruction::AShr:
1689-
applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_shra});
1690-
break;
1691-
default:
1692-
// TODO: Salvage constants from each kind of binop we know about.
1693-
return false;
1694-
}
1678+
switch (BI->getOpcode()) {
1679+
case Instruction::Add:
1680+
return applyOffset(Val);
1681+
case Instruction::Sub:
1682+
return applyOffset(-int64_t(Val));
1683+
case Instruction::Mul:
1684+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_mul});
1685+
case Instruction::SDiv:
1686+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_div});
1687+
case Instruction::SRem:
1688+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_mod});
1689+
case Instruction::Or:
1690+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_or});
1691+
case Instruction::And:
1692+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_and});
1693+
case Instruction::Xor:
1694+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_xor});
1695+
case Instruction::Shl:
1696+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shl});
1697+
case Instruction::LShr:
1698+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shr});
1699+
case Instruction::AShr:
1700+
return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shra});
1701+
default:
1702+
// TODO: Salvage constants from each kind of binop we know about.
1703+
return nullptr;
16951704
}
1696-
return true;
16971705
} else if (isa<LoadInst>(&I)) {
1698-
MetadataAsValue *AddrMD = wrapMD(I.getOperand(0));
1699-
for (auto *DII : DbgUsers) {
1700-
// Rewrite the load into DW_OP_deref.
1701-
auto *DIExpr = DII->getExpression();
1702-
DIExpr = DIExpression::prepend(DIExpr, DIExpression::WithDeref);
1703-
DII->setOperand(0, AddrMD);
1704-
DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr));
1705-
LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');
1706-
}
1707-
return true;
1706+
// Rewrite the load into DW_OP_deref.
1707+
return DIExpression::prepend(SrcDIExpr, DIExpression::WithDeref);
17081708
}
1709-
return false;
1709+
return nullptr;
17101710
}
17111711

17121712
/// A replacement for a dbg.value expression.

0 commit comments

Comments
 (0)