From 84ca706be1dba3b9a7eb10a3620dfd13f089907e Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Tue, 5 Feb 2019 11:11:28 +0000 Subject: [PATCH] [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 --- llvm/include/llvm/Transforms/Utils/Local.h | 12 +++ llvm/lib/Transforms/Utils/Local.cpp | 164 ++++++++++++++--------------- 2 files changed, 94 insertions(+), 82 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h index eed17d7..22276d1 100644 --- a/llvm/include/llvm/Transforms/Utils/Local.h +++ b/llvm/include/llvm/Transforms/Utils/Local.h @@ -341,6 +341,18 @@ void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress, /// Returns true if any debug users were updated. bool salvageDebugInfo(Instruction &I); +/// Implementation of salvageDebugInfo, applying only to instructions in +/// \p Insns, rather than all debug users of \p I. +bool salvageDebugInfoForDbgValues(Instruction &I, + ArrayRef Insns); + +/// Given an instruction \p I and DIExpression \p DIExpr operating on it, write +/// the effects of \p I into the returned DIExpression, or return nullptr if +/// it cannot be salvaged. \p StackVal: whether DW_OP_stack_value should be +/// appended to the expression. +DIExpression *salvageDebugInfoImpl(Instruction &I, DIExpression *DIExpr, + bool StackVal); + /// Point debug users of \p From to \p To or salvage them. Use this function /// only when replacing all uses of \p From with \p To, with a guarantee that /// \p From is going to be deleted. diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index a05a7a2..e5238a9 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1593,120 +1593,120 @@ bool llvm::salvageDebugInfo(Instruction &I) { if (DbgUsers.empty()) return false; - auto &M = *I.getModule(); - auto &DL = M.getDataLayout(); + return salvageDebugInfoForDbgValues(I, DbgUsers); +} + +bool llvm::salvageDebugInfoForDbgValues( + Instruction &I, ArrayRef DbgUsers) { auto &Ctx = I.getContext(); auto wrapMD = [&](Value *V) { return wrapValueInMetadata(Ctx, V); }; - auto doSalvage = [&](DbgVariableIntrinsic *DII, SmallVectorImpl &Ops) { - auto *DIExpr = DII->getExpression(); - if (!Ops.empty()) { - // Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they - // are implicitly pointing out the value as a DWARF memory location - // description. - bool WithStackValue = isa(DII); - DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue); - } + for (auto *DII : DbgUsers) { + // Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they + // are implicitly pointing out the value as a DWARF memory location + // description. + bool StackValue = isa(DII); + + DIExpression *DIExpr = + salvageDebugInfoImpl(I, DII->getExpression(), StackValue); + + // salvageDebugInfoImpl should fail on examining the first element of + // DbgUsers, or none of them. + if (!DIExpr) + return false; + DII->setOperand(0, wrapMD(I.getOperand(0))); DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr)); LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); + } + + return true; +} + +DIExpression *llvm::salvageDebugInfoImpl(Instruction &I, + DIExpression *SrcDIExpr, + bool WithStackValue) { + auto &M = *I.getModule(); + auto &DL = M.getDataLayout(); + + // Apply a vector of opcodes to the source DIExpression. + auto doSalvage = [&](SmallVectorImpl &Ops) -> DIExpression * { + DIExpression *DIExpr = SrcDIExpr; + if (!Ops.empty()) { + DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue); + } + return DIExpr; }; - auto applyOffset = [&](DbgVariableIntrinsic *DII, uint64_t Offset) { + // Apply the given offset to the source DIExpression. + auto applyOffset = [&](uint64_t Offset) -> DIExpression * { SmallVector Ops; DIExpression::appendOffset(Ops, Offset); - doSalvage(DII, Ops); + return doSalvage(Ops); }; - auto applyOps = [&](DbgVariableIntrinsic *DII, - std::initializer_list Opcodes) { + // initializer-list helper for applying operators to the source DIExpression. + auto applyOps = + [&](std::initializer_list Opcodes) -> DIExpression * { SmallVector Ops(Opcodes); - doSalvage(DII, Ops); + return doSalvage(Ops); }; if (auto *CI = dyn_cast(&I)) { if (!CI->isNoopCast(DL)) - return false; + return nullptr; // No-op casts are irrelevant for debug info. - MetadataAsValue *CastSrc = wrapMD(I.getOperand(0)); - for (auto *DII : DbgUsers) { - DII->setOperand(0, CastSrc); - LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); - } - return true; + return SrcDIExpr; } else if (auto *GEP = dyn_cast(&I)) { unsigned BitWidth = M.getDataLayout().getIndexSizeInBits(GEP->getPointerAddressSpace()); - // Rewrite a constant GEP into a DIExpression. Since we are performing - // arithmetic to compute the variable's *value* in the DIExpression, we - // need to mark the expression with a DW_OP_stack_value. + // Rewrite a constant GEP into a DIExpression. APInt Offset(BitWidth, 0); - if (GEP->accumulateConstantOffset(M.getDataLayout(), Offset)) - for (auto *DII : DbgUsers) - applyOffset(DII, Offset.getSExtValue()); - return true; + if (GEP->accumulateConstantOffset(M.getDataLayout(), Offset)) { + return applyOffset(Offset.getSExtValue()); + } else { + return nullptr; + } } else if (auto *BI = dyn_cast(&I)) { // Rewrite binary operations with constant integer operands. auto *ConstInt = dyn_cast(I.getOperand(1)); if (!ConstInt || ConstInt->getBitWidth() > 64) - return false; + return nullptr; uint64_t Val = ConstInt->getSExtValue(); - for (auto *DII : DbgUsers) { - switch (BI->getOpcode()) { - case Instruction::Add: - applyOffset(DII, Val); - break; - case Instruction::Sub: - applyOffset(DII, -int64_t(Val)); - break; - case Instruction::Mul: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_mul}); - break; - case Instruction::SDiv: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_div}); - break; - case Instruction::SRem: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_mod}); - break; - case Instruction::Or: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_or}); - break; - case Instruction::And: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_and}); - break; - case Instruction::Xor: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_xor}); - break; - case Instruction::Shl: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_shl}); - break; - case Instruction::LShr: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_shr}); - break; - case Instruction::AShr: - applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_shra}); - break; - default: - // TODO: Salvage constants from each kind of binop we know about. - return false; - } + switch (BI->getOpcode()) { + case Instruction::Add: + return applyOffset(Val); + case Instruction::Sub: + return applyOffset(-int64_t(Val)); + case Instruction::Mul: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_mul}); + case Instruction::SDiv: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_div}); + case Instruction::SRem: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_mod}); + case Instruction::Or: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_or}); + case Instruction::And: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_and}); + case Instruction::Xor: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_xor}); + case Instruction::Shl: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shl}); + case Instruction::LShr: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shr}); + case Instruction::AShr: + return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shra}); + default: + // TODO: Salvage constants from each kind of binop we know about. + return nullptr; } - return true; } else if (isa(&I)) { - MetadataAsValue *AddrMD = wrapMD(I.getOperand(0)); - for (auto *DII : DbgUsers) { - // Rewrite the load into DW_OP_deref. - auto *DIExpr = DII->getExpression(); - DIExpr = DIExpression::prepend(DIExpr, DIExpression::WithDeref); - DII->setOperand(0, AddrMD); - DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr)); - LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); - } - return true; + // Rewrite the load into DW_OP_deref. + return DIExpression::prepend(SrcDIExpr, DIExpression::WithDeref); } - return false; + return nullptr; } /// A replacement for a dbg.value expression. -- 2.7.4