Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -1481,8 +1481,58 @@ return AI->getAllocatedType() && AI->getAllocatedType()->isStructTy(); } -/// LowerDbgDeclare - Lowers llvm.dbg.declare intrinsics into appropriate set -/// of llvm.dbg.value intrinsics. +static bool ConvertIndirectDbgIntrinsicToDbgValues(DbgDeclareInst *DII, + DIBuilder &DIB) { + assert(DII->isAddressOfVariable()); + AllocaInst *AI = dyn_cast_or_null(DII->getVariableLocation()); + // If this is an alloca for a scalar variable, insert a dbg.value at each + // load and store to the alloca and erase the dbg.declare. The dbg.values + // allow tracking a variable even if it is not stored on the stack, while the + // dbg.declare can only describe the stack slot (and at a lexical-scope + // granularity). Later passes will attempt to elide the stack slot. + if (!AI || isArray(AI) || isStructure(AI)) + return false; + + // A volatile load/store means that the alloca can't be elided anyway. + if (llvm::any_of(AI->users(), [](User *U) -> bool { + if (LoadInst *LI = dyn_cast(U)) + return LI->isVolatile(); + if (StoreInst *SI = dyn_cast(U)) + return SI->isVolatile(); + return false; + })) + return false; + + SmallVector WorkList; + WorkList.push_back(AI); + while (!WorkList.empty()) { + const Value *V = WorkList.pop_back_val(); + for (auto &AIUse : V->uses()) { + User *U = AIUse.getUser(); + if (StoreInst *SI = dyn_cast(U)) { + if (AIUse.getOperandNo() == 1) + ConvertDebugDeclareToDebugValue(DII, SI, DIB); + } else if (LoadInst *LI = dyn_cast(U)) { + ConvertDebugDeclareToDebugValue(DII, LI, DIB); + } else if (CallInst *CI = dyn_cast(U)) { + // This is a call by-value or some other instruction that takes a + // pointer to the variable. Insert a *value* intrinsic that describes + // the variable by dereferencing the alloca. + if (!CI->isLifetimeStartOrEnd()) { + DebugLoc NewLoc = getDebugValueLoc(DII, nullptr); + auto *Expr = + DIExpression::append(DII->getExpression(), dwarf::DW_OP_deref); + DIB.insertDbgValueIntrinsic(AI, DII->getVariable(), Expr, NewLoc, CI); + } + } else if (BitCastInst *BI = dyn_cast(U)) { + if (BI->getType()->isPointerTy()) + WorkList.push_back(BI); + } + } + } + return true; +} + bool llvm::LowerDbgDeclare(Function &F) { bool Changed = false; DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false); @@ -1495,63 +1545,16 @@ if (Dbgs.empty()) return Changed; - for (auto &I : Dbgs) { - DbgDeclareInst *DDI = I; - AllocaInst *AI = dyn_cast_or_null(DDI->getAddress()); - // If this is an alloca for a scalar variable, insert a dbg.value - // at each load and store to the alloca and erase the dbg.declare. - // The dbg.values allow tracking a variable even if it is not - // stored on the stack, while the dbg.declare can only describe - // the stack slot (and at a lexical-scope granularity). Later - // passes will attempt to elide the stack slot. - if (!AI || isArray(AI) || isStructure(AI)) - continue; - - // A volatile load/store means that the alloca can't be elided anyway. - if (llvm::any_of(AI->users(), [](User *U) -> bool { - if (LoadInst *LI = dyn_cast(U)) - return LI->isVolatile(); - if (StoreInst *SI = dyn_cast(U)) - return SI->isVolatile(); - return false; - })) - continue; - - SmallVector WorkList; - WorkList.push_back(AI); - while (!WorkList.empty()) { - const Value *V = WorkList.pop_back_val(); - for (auto &AIUse : V->uses()) { - User *U = AIUse.getUser(); - if (StoreInst *SI = dyn_cast(U)) { - if (AIUse.getOperandNo() == 1) - ConvertDebugDeclareToDebugValue(DDI, SI, DIB); - } else if (LoadInst *LI = dyn_cast(U)) { - ConvertDebugDeclareToDebugValue(DDI, LI, DIB); - } else if (CallInst *CI = dyn_cast(U)) { - // This is a call by-value or some other instruction that takes a - // pointer to the variable. Insert a *value* intrinsic that describes - // the variable by dereferencing the alloca. - if (!CI->isLifetimeStartOrEnd()) { - DebugLoc NewLoc = getDebugValueLoc(DDI, nullptr); - auto *DerefExpr = - DIExpression::append(DDI->getExpression(), dwarf::DW_OP_deref); - DIB.insertDbgValueIntrinsic(AI, DDI->getVariable(), DerefExpr, - NewLoc, CI); - } - } else if (BitCastInst *BI = dyn_cast(U)) { - if (BI->getType()->isPointerTy()) - WorkList.push_back(BI); - } - } + for (auto *DDI : Dbgs) { + if (ConvertIndirectDbgIntrinsicToDbgValues(DDI, DIB)) { + DDI->eraseFromParent(); + Changed = true; } - DDI->eraseFromParent(); - Changed = true; } if (Changed) - for (BasicBlock &BB : F) - RemoveRedundantDbgInstrs(&BB); + for (BasicBlock &BB : F) + RemoveRedundantDbgInstrs(&BB); return Changed; }