diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h --- a/llvm/include/llvm/Transforms/Utils/Local.h +++ b/llvm/include/llvm/Transforms/Utils/Local.h @@ -374,8 +374,10 @@ /// Implementation of salvageDebugInfo, applying only to instructions in -/// \p Insns, rather than all debug users of \p I. -bool salvageDebugInfoForDbgValues(Instruction &I, +/// \p Insns, rather than all debug users from findDbgUsers( \p I). +/// Returns true if any debug users were updated. +/// Mark undef if salvaging cannot be completed. +void salvageDebugInfoForDbgValues(Instruction &I, ArrayRef Insns); /// Given an instruction \p I and DIExpression \p DIExpr operating on it, write diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3337,46 +3337,42 @@ // here, but that computation has been sunk. SmallVector DbgUsers; findDbgUsers(DbgUsers, I); - for (auto *DII : reverse(DbgUsers)) { - if (DII->getParent() == SrcBlock) { - if (isa(DII)) { - // A dbg.declare instruction should not be cloned, since there can only be - // one per variable fragment. It should be left in the original place since - // sunk instruction is not an alloca(otherwise we could not be here). - // But we need to update arguments of dbg.declare instruction, so that it - // would not point into sunk instruction. - if (!isa(I)) - continue; // dbg.declare points at something it shouldn't - - DII->setOperand( - 0, MetadataAsValue::get(I->getContext(), - ValueAsMetadata::get(I->getOperand(0)))); - continue; - } - // dbg.value is in the same basic block as the sunk inst, see if we can - // salvage it. Clone a new copy of the instruction: on success we need - // both salvaged and unsalvaged copies. - SmallVector TmpUser{ - cast(DII->clone())}; - - if (!salvageDebugInfoForDbgValues(*I, TmpUser)) { - // We are unable to salvage: sink the cloned dbg.value, and mark the - // original as undef, terminating any earlier variable location. - LLVM_DEBUG(dbgs() << "SINK: " << *DII << '\n'); - TmpUser[0]->insertBefore(&*InsertPos); - Value *Undef = UndefValue::get(I->getType()); - DII->setOperand(0, MetadataAsValue::get(DII->getContext(), - ValueAsMetadata::get(Undef))); - } else { - // We successfully salvaged: place the salvaged dbg.value in the - // original location, and move the unmodified dbg.value to sink with - // the sunk inst. - TmpUser[0]->insertBefore(DII); - DII->moveBefore(&*InsertPos); - } + // Update the arguments of a dbg.declare instruction, so that it + // does not point into a sunk instruction. + auto updateDbgDeclare = [&I](DbgVariableIntrinsic *DII) { + if (!isa(DII)) + return false; + + if (isa(I)) + DII->setOperand( + 0, MetadataAsValue::get(I->getContext(), + ValueAsMetadata::get(I->getOperand(0)))); + return true; + }; + + SmallVector DIIClones; + for (auto User : DbgUsers) { + // A dbg.declare instruction should not be cloned, since there can only be + // one per variable fragment. It should be left in the original place + // because the sunk instruction is not an alloca (otherwise we could not be + // here). + if (User->getParent() != SrcBlock || updateDbgDeclare(User)) + continue; + + DIIClones.emplace_back(cast(User->clone())); + LLVM_DEBUG(dbgs() << "CLONE: " << *DIIClones.back() << '\n'); + } + + // Perform salvaging without the clones, then sink the clones. + if (!DIIClones.empty()) { + salvageDebugInfoForDbgValues(*I, DbgUsers); + for (auto &DIIClone : DIIClones) { + DIIClone->insertBefore(&*InsertPos); + LLVM_DEBUG(dbgs() << "SINK: " << *DIIClone << '\n'); } } + return true; } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1628,23 +1628,18 @@ return MetadataAsValue::get(C, ValueAsMetadata::get(V)); } -static bool attemptToSalvageDebugInfo(Instruction &I) { +/// Where possible to salvage debug information for \p I do so +/// and return True. If not possible mark undef and return False. +void llvm::salvageDebugInfo(Instruction &I) { SmallVector DbgUsers; findDbgUsers(DbgUsers, &I); - if (DbgUsers.empty()) - return false; - - return salvageDebugInfoForDbgValues(I, DbgUsers); -} - -void llvm::salvageDebugInfo(Instruction &I) { - if (!attemptToSalvageDebugInfo(I)) - replaceDbgUsesWithUndef(&I); + salvageDebugInfoForDbgValues(I, DbgUsers); } -bool llvm::salvageDebugInfoForDbgValues( +void llvm::salvageDebugInfoForDbgValues( Instruction &I, ArrayRef DbgUsers) { auto &Ctx = I.getContext(); + bool Salvaged = false; auto wrapMD = [&](Value *V) { return wrapValueInMetadata(Ctx, V); }; for (auto *DII : DbgUsers) { @@ -1659,14 +1654,22 @@ // salvageDebugInfoImpl should fail on examining the first element of // DbgUsers, or none of them. if (!DIExpr) - return false; + break; DII->setOperand(0, wrapMD(I.getOperand(0))); DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr)); LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); + Salvaged = true; } - return true; + if (Salvaged) + return; + + for (auto *DII : DbgUsers) { + Value *Undef = UndefValue::get(I.getType()); + DII->setOperand(0, MetadataAsValue::get(DII->getContext(), + ValueAsMetadata::get(Undef))); + } } DIExpression *llvm::salvageDebugInfoImpl(Instruction &I, diff --git a/llvm/test/Transforms/InstCombine/debuginfo_add.ll b/llvm/test/Transforms/InstCombine/debuginfo_add.ll --- a/llvm/test/Transforms/InstCombine/debuginfo_add.ll +++ b/llvm/test/Transforms/InstCombine/debuginfo_add.ll @@ -36,8 +36,8 @@ ; The add is later eliminated, so we verify that the dbg.value is salvaged by using DW_OP_minus. ; CHECK-LABEL: for.body.lr.ph: ; CHECK-NEXT: %0 = load - ; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %0, metadata !25, metadata !DIExpression()), !dbg ! ; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %0, metadata !26, metadata !DIExpression(DW_OP_constu, 4096, DW_OP_minus, DW_OP_stack_value)), !dbg ! + ; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %0, metadata !25, metadata !DIExpression()), !dbg ! br label %for.body, !dbg !32 for.body: ; preds = %for.body.lr.ph, %for.body