diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h index c5a447a5d5fa..f09ebe5e2471 100644 --- a/llvm/include/llvm/Transforms/Utils/Local.h +++ b/llvm/include/llvm/Transforms/Utils/Local.h @@ -16,6 +16,7 @@ #define LLVM_TRANSFORMS_UTILS_LOCAL_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TinyPtrVector.h" @@ -333,6 +334,16 @@ void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress, /// DIExpression. void salvageDebugInfo(Instruction &I); +/// Assuming the instruction \p From is going to be deleted, insert replacement +/// dbg.value intrinsics for each debug user of \p From. The newly-inserted +/// dbg.values refer to \p To instead of \p From. Each replacement dbg.value +/// has the same location and variable as the debug user it replaces, has a +/// DIExpression determined by the result of \p RewriteExpr applied to an old +/// debug user of \p From, and is placed before \p InsertBefore. +void insertReplacementDbgValues( + Instruction &From, Instruction &To, Instruction &InsertBefore, + function_ref RewriteExpr); + /// Remove all instructions from a basic block other than it's terminator /// and any present EH pad instructions. unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 9f297b0aab08..aa86dddf04d0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -268,17 +268,12 @@ Instruction *InstCombiner::commonCastTransforms(CastInst &CI) { // the second cast (CI). CSrc will then have a good chance of being dead. auto *Res = CastInst::Create(NewOpc, CSrc->getOperand(0), CI.getType()); - // If the eliminable cast has debug users, insert a debug value after the - // cast pointing to the new Value. - SmallVector CSrcDbgInsts; - findDbgUsers(CSrcDbgInsts, CSrc); - if (CSrcDbgInsts.size()) { - DIBuilder DIB(*CI.getModule()); - for (auto *DII : CSrcDbgInsts) - DIB.insertDbgValueIntrinsic( - Res, DII->getVariable(), DII->getExpression(), - DII->getDebugLoc().get(), &*std::next(CI.getIterator())); - } + // Replace debug users of the eliminable cast by emitting debug values + // which refer to the new cast. + insertReplacementDbgValues( + *CSrc, *Res, *std::next(CI.getIterator()), + [](DbgInfoIntrinsic &OldDII) { return OldDII.getExpression(); }); + return Res; } } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 3a43025cb832..7dd74a1aa40b 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1671,6 +1671,24 @@ void llvm::salvageDebugInfo(Instruction &I) { } } +void llvm::insertReplacementDbgValues( + Instruction &From, Instruction &To, Instruction &InsertBefore, + function_ref RewriteExpr) { + // Collect all debug users of From. + SmallVector Users; + findDbgUsers(Users, &From); + if (Users.empty()) + return; + + // Insert a replacement debug value for each old debug user. It's assumed + // that the old debug users will be erased later. + DIBuilder DIB(*From.getModule()); + for (auto *OldDII : Users) + DIB.insertDbgValueIntrinsic(&To, OldDII->getVariable(), + RewriteExpr(*OldDII), + OldDII->getDebugLoc().get(), &InsertBefore); +} + unsigned llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) { unsigned NumDeadInst = 0; // Delete the instructions backwards, as it has a reduced likelihood of