Index: llvm/include/llvm/Transforms/Utils/Local.h =================================================================== --- llvm/include/llvm/Transforms/Utils/Local.h +++ llvm/include/llvm/Transforms/Utils/Local.h @@ -358,12 +358,6 @@ /// 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 Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3438,46 +3438,50 @@ // 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 + // We update arguments of so that the instruction does not point into sunk + // instruction. + auto updateDbgDeclare = [&I](DbgVariableIntrinsic *DII) { + if (isa(DII)) { + if (isa(I)) 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); - } + return true; + } + return false; + }; + + // We do not want salvageDebugInfo() to modify the clones. Prevent + // modification by setting each clones Op0 to Undef. The original value + // is restored when the clone is sunk. + SmallVector, 2> 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; + + DbgVariableIntrinsic *clone = cast(User->clone()); + DIIClones.emplace_back(std::make_pair(clone, clone->getOperand(0))); + LLVM_DEBUG(dbgs() << "CLONE: " << DIIClones.back().first << '\n'); + Value *Undef = UndefValue::get(I->getType()); + clone->setOperand(0, MetadataAsValue::get(clone->getContext(), + ValueAsMetadata::get(Undef))); + } + + if (!DIIClones.empty()) { + salvageDebugInfo(*I); + for (auto &DIIClone : DIIClones) { + DIIClone.first->setOperand(0, DIIClone.second); + DIIClone.first->insertBefore(&*InsertPos); + LLVM_DEBUG(dbgs() << "SINK: " << *DIIClone.first << '\n'); } } + return true; } Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -1619,24 +1619,9 @@ return MetadataAsValue::get(C, ValueAsMetadata::get(V)); } -static bool attemptToSalvageDebugInfo(Instruction &I) { - SmallVector DbgUsers; - findDbgUsers(DbgUsers, &I); - if (DbgUsers.empty()) - return false; - - return salvageDebugInfoForDbgValues(I, DbgUsers); -} - -bool llvm::salvageDebugInfo(Instruction &I) { - bool salvaged = attemptToSalvageDebugInfo(I); - if (!salvaged) - replaceDbgUsesWithUndef(&I); - return salvaged; -} - -bool llvm::salvageDebugInfoForDbgValues( - Instruction &I, ArrayRef DbgUsers) { +static bool +salvageDebugInfoForDbgValues(Instruction &I, + ArrayRef DbgUsers) { auto &Ctx = I.getContext(); auto wrapMD = [&](Value *V) { return wrapValueInMetadata(Ctx, V); }; @@ -1662,6 +1647,27 @@ return true; } +/// If the instruction \p I has any debug users salvage the debug +/// information and return True. Else return False. +static bool attemptToSalvageDebugInfo(Instruction &I) { + SmallVector DbgUsers; + findDbgUsers(DbgUsers, &I); + if (DbgUsers.empty()) + return false; + + return salvageDebugInfoForDbgValues(I, DbgUsers); +} + +/// Where possible to salvage debug information for \p I do so +/// and return True. If not possible mark uses of I as undef and +/// return False. +bool llvm::salvageDebugInfo(Instruction &I) { + bool salvaged = attemptToSalvageDebugInfo(I); + if (!salvaged) + replaceDbgUsesWithUndef(&I); + return salvaged; +} + DIExpression *llvm::salvageDebugInfoImpl(Instruction &I, DIExpression *SrcDIExpr, bool WithStackValue) { Index: llvm/test/Transforms/InstCombine/debuginfo_add.ll =================================================================== --- llvm/test/Transforms/InstCombine/debuginfo_add.ll +++ 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