Index: llvm/include/llvm/IR/Metadata.h =================================================================== --- llvm/include/llvm/IR/Metadata.h +++ llvm/include/llvm/IR/Metadata.h @@ -1001,6 +1001,8 @@ return cast(N.release()->replaceWithDistinctImpl()); } + void replaceName(MDString *NewName) { setOperand(1, NewName); } + private: MDNode *replaceWithPermanentImpl(); MDNode *replaceWithUniquedImpl(); Index: llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h =================================================================== --- llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -50,6 +50,8 @@ SmallVectorImpl *Updates, bool KeepOneInputPHIs = false); +void DeleteUselessDbgInfo(ArrayRef ToRemovedBBs); + /// Delete the specified block, which must have no predecessors. void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr, bool KeepOneInputPHIs = false); Index: llvm/lib/Transforms/Coroutines/CoroFrame.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/InstIterator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/OptimizedStructLayout.h" #include "llvm/Support/circular_raw_ostream.h" @@ -1052,6 +1053,20 @@ return CleanupRet; } +static void getNewValueStorage(Value *V, Value *&NewValue, DIExpression *&Expr) { + assert(V && "V should not be null"); + while (true) { + if (auto *GEPInst = dyn_cast(V)) { + Expr = llvm::salvageDebugInfoImpl(*GEPInst, Expr, false); + V = GEPInst->getOperand(0); + } else if (auto *BCInst = dyn_cast(V)) + V = BCInst->getOperand(0); + else + break; + } + NewValue = V; +} + // Replace all alloca and SSA values that are accessed across suspend points // with GetElementPointer from coroutine frame + loads and stores. Create an // AllocaSpillBB that will become the new entry block for the resume parts of @@ -1077,6 +1092,7 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { auto *CB = Shape.CoroBegin; + auto *M = CB->getModule(); LLVMContext &C = CB->getContext(); IRBuilder<> Builder(CB->getNextNode()); StructType *FrameTy = Shape.FrameTy; @@ -1084,6 +1100,8 @@ auto *FramePtr = cast(Builder.CreateBitCast(CB, FramePtrTy, "FramePtr")); DominatorTree DT(*CB->getFunction()); + // copy dbg from entry block if the dbg intrinsic existed + std::unique_ptr DIB = std::make_unique(*M, false); // Create a GEP with the given index into the coroutine frame for the original // value Orig. Appends an extra 0 index for array-allocas, preserving the @@ -1124,6 +1142,10 @@ // Create a store instruction storing the value into the // coroutine frame. Instruction *InsertPt = nullptr; + DbgVariableIntrinsic *DebugInstrinsic = nullptr; + SmallVector DbgUsers; + // find all dbg user + findDbgUsers(DbgUsers, Def); if (auto *Arg = dyn_cast(Def)) { // For arguments, we will place the store instruction right after // the coroutine frame pointer instruction, i.e. bitcast of @@ -1134,6 +1156,15 @@ // from the coroutine function. Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::NoCapture); + // Get debug intrinsic for argument + auto Iter = llvm::find_if(DbgUsers, [](DbgVariableIntrinsic *Dbg) { + DILocalVariable *Variable = Dbg->getVariable(); + return Variable->isParameter() && !Variable->isArtificial(); + }); + + // if we get multiple results, just pick one + if (Iter != DbgUsers.end()) + DebugInstrinsic = *Iter; } else if (auto *CSI = dyn_cast(Def)) { // Don't spill immediately after a suspend; splitting assumes // that the suspend will be followed by a branch. @@ -1185,6 +1216,21 @@ CurrentReload = Builder.CreateLoad( FrameTy->getElementType(FrameData.getFieldIndex(E.first)), GEP, E.first->getName() + Twine(".reload")); + + if (DIB && DebugInstrinsic) { + auto *CurVar = DebugInstrinsic->getVariable(); + assert(CurVar && "CurVar should not be null"); + const DILocation *Loc = DebugInstrinsic->getDebugLoc().get(); + + // try to get scope form gep or use original one + Instruction *InstGEP = cast(GEP); + DIExpression *NewExpr = DIExpression::append( + DebugInstrinsic->getExpression(), dwarf::DW_OP_deref); + Value *NewValue = InstGEP; + getNewValueStorage(InstGEP, NewValue, NewExpr); + DIB->insertDbgValueIntrinsic(NewValue, CurVar, NewExpr, Loc, + cast(CurrentReload)); + } } // If we have a single edge PHINode, remove it and replace it with a Index: llvm/lib/Transforms/Utils/BasicBlockUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -85,6 +85,50 @@ } } +void llvm::DeleteUselessDbgInfo(ArrayRef ToRemovedBBs) { + for (BasicBlock *BB : ToRemovedBBs) { + for (auto &I : *BB) { + if (auto *Dbg = dyn_cast_or_null(&I)) { + bool SafeToRemove = false; + auto *Variable = Dbg->getVariable(); + if (Variable == nullptr) + continue; + + auto *MetaVal = MetadataAsValue::get(BB->getContext(), Variable); + do { + // 1. if user is empty, we can safe to remove it + if (MetaVal->user_empty()) { + SafeToRemove = true; + break; + } + + // 2. if has use, we will keep it. + SafeToRemove = true; + for (Use &U : MetaVal->uses()) { + if (auto *I = dyn_cast_or_null(U.getUser())) { + BasicBlock *CurBB = I->getParent(); + auto FindBBFn = [&](BasicBlock *BB) { return CurBB == BB; }; + if (!llvm::any_of(ToRemovedBBs, FindBBFn)) { + SafeToRemove = false; + break; + } + } + } + } while (0); + + if (SafeToRemove) { + // TODO: it is better to remove the useless metadata from Module, but + // we can not do it now + LLVM_DEBUG(dbgs() << "remove metadata:\n"; MetaVal->dump();); + std::string Name = Variable->getName().data(); + Name += "__fake_param_" + Name; + Variable->replaceName(MDString::get(BB->getContext(), Name)); + } + } + } + } +} + void llvm::DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU, bool KeepOneInputPHIs) { DeleteDeadBlocks({BB}, DTU, KeepOneInputPHIs); @@ -101,6 +145,9 @@ assert(Dead.count(Pred) && "All predecessors must be dead!"); #endif + // remove dbgs + DeleteUselessDbgInfo(BBs); + SmallVector Updates; DetatchDeadBlocks(BBs, DTU ? &Updates : nullptr, KeepOneInputPHIs); Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -2380,6 +2380,7 @@ std::vector Updates; for (auto *BB : DeadBlockSet) { SmallSetVector UniqueSuccessors; + DeleteUselessDbgInfo({BB}); for (BasicBlock *Successor : successors(BB)) { if (!DeadBlockSet.count(Successor)) Successor->removePredecessor(BB);