Index: lldb/source/Expression/IRInterpreter.cpp =================================================================== --- lldb/source/Expression/IRInterpreter.cpp +++ lldb/source/Expression/IRInterpreter.cpp @@ -81,6 +81,7 @@ break; case llvm::Intrinsic::dbg_declare: case llvm::Intrinsic::dbg_value: + case llvm::Intrinsic::dbg_derefval: return true; } } Index: llvm/docs/SourceLevelDebugging.rst =================================================================== --- llvm/docs/SourceLevelDebugging.rst +++ llvm/docs/SourceLevelDebugging.rst @@ -250,6 +250,37 @@ be indirect (i.e, a pointer to the source variable), provided that interpreting the complex expression derives the direct value. +``llvm.dbg.derefval`` +^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + void @llvm.dbg.derefval(metadata, metadata, metadata) + +This intrinsic is identical to `llvm.dbg.value`, except that it is used to +describe dereferenced value of a pointer variable, when the pointer itself is +no longer available in the program. + +The first argument must be a `local variable `_. +The second argument is a `local variable `_ +containing a description of the variable. The third argument is a +`complex expression `_. + +An `llvm.dbg.derefval` intrinsic is useful when location which the variable +points to is optimized out, but the dereferenced value is known. + +.. code-block:: text + + call void @llvm.dbg.derefval(metadata !1, metadata !2, + metadata !DIExpression(DW_OP_LLVM_implicit_pointer, + DW_OP_LLVM_arg0, 0)) + !1 = !DILocalVariable(name: "arr", ...) ; int arr[5] + !2 = !DILocalVariable(name: "ptr", ...) ; int *ptr; ptr=arr; + ... + call void @llvm.dbg.derefval(metadata i32 1, metadata !1, + metadata !DIExpression(DW_OP_LLVM_arg0)) + !1 = !DILocalVariable(name: "ptr", ...) ; int *ptr;tmp=1;ptr=&tmp; + Object lifetimes and scoping ============================ Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -819,6 +819,7 @@ case Intrinsic::sideeffect: case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: case Intrinsic::dbg_label: case Intrinsic::invariant_start: case Intrinsic::invariant_end: Index: llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -366,6 +366,11 @@ const MDNode *Variable, const MDNode *Expr); + /// Build and insert a DBG_VALUE instructions specifying that the dereferenced + /// value of \p Variable is given by \p V (suitably modified by \p Expr). + MachineInstrBuilder buildDerefDbgValue(const Value *V, const MDNode *Variable, + const MDNode *Expr); + /// Build and insert a DBG_LABEL instructions specifying that \p Label is /// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label". MachineInstrBuilder buildDbgLabel(const MDNode *Label); Index: llvm/include/llvm/CodeGen/MachineInstr.h =================================================================== --- llvm/include/llvm/CodeGen/MachineInstr.h +++ llvm/include/llvm/CodeGen/MachineInstr.h @@ -403,6 +403,10 @@ /// this DBG_VALUE instruction. const DILocalVariable *getDebugVariable() const; + /// Return the debug implicit variable referenced by + /// this DBG_VALUE instruction. + const DIVariable *getDebugImplicitVariable() const; + /// Return the complex address expression referenced by /// this DBG_VALUE instruction. const DIExpression *getDebugExpression() const; Index: llvm/include/llvm/CodeGen/MachineInstrBuilder.h =================================================================== --- llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -235,6 +235,18 @@ return *this; } + const MachineInstrBuilder &addImplicitPtrMetadata(const MDNode *MD) const { + MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); + assert(((MI->isDebugValue()) + ? static_cast(MI->getDebugImplicitVariable()) + : true) && + "first MDNode argument of a DBG_VALUE not a DIVariable"); + assert((MI->isDebugLabel() ? static_cast(MI->getDebugLabel()) + : true) && + "first MDNode argument of a DBG_LABEL not a label"); + return *this; + } + const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const { MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex)); return *this; Index: llvm/include/llvm/IR/DIBuilder.h =================================================================== --- llvm/include/llvm/IR/DIBuilder.h +++ llvm/include/llvm/IR/DIBuilder.h @@ -45,6 +45,7 @@ DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler. Function *DeclareFn; ///< llvm.dbg.declare Function *ValueFn; ///< llvm.dbg.value + Function *DerefvalFn; ///< llvm.dbg.derefval Function *LabelFn; ///< llvm.dbg.label SmallVector AllEnumTypes; @@ -92,6 +93,16 @@ DIExpression *Expr, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore); + /// Internal helper for insertDbgDerefValueIntrinsic. + Instruction *insertDbgDerefValueIntrinsic( + llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore); + + /// Internal helper for insertDbgDerefValueIntrinsic. + Instruction *insertDbgDerefValueIntrinsic( + DIVariable *Val, DILocalVariable *VarInfo, DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore); + public: /// Construct a builder for a module. /// @@ -851,6 +862,30 @@ const DILocation *DL, Instruction *InsertBefore); + /// Insert a new llvm.dbg.derefval intrinsic call. + /// \param Val dereferenced value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. + Instruction *insertDbgDerefValueIntrinsic(llvm::Value *Val, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, + Instruction *InsertBefore); + + /// Insert a new llvm.dbg.derefval intrinsic call. + /// \param Val dereferenced value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. + Instruction *insertDbgDerefValueIntrinsic(DIVariable *Val, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, + Instruction *InsertBefore); + /// Replace the vtable holder in the given type. /// /// If this creates a self reference, it may orphan some unresolved cycles Index: llvm/include/llvm/IR/InstVisitor.h =================================================================== --- llvm/include/llvm/IR/InstVisitor.h +++ llvm/include/llvm/IR/InstVisitor.h @@ -204,6 +204,9 @@ // Handle the special instrinsic instruction classes. RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgVariableIntrinsic);} RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgVariableIntrinsic);} + RetTy visitDbgDerefValueInst(DbgDerefValueInst &I) { + DELEGATE(DbgVariableIntrinsic); + } RetTy visitDbgVariableIntrinsic(DbgVariableIntrinsic &I) { DELEGATE(DbgInfoIntrinsic);} RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);} @@ -306,6 +309,8 @@ default: DELEGATE(IntrinsicInst); case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); case Intrinsic::dbg_value: DELEGATE(DbgValueInst); + case Intrinsic::dbg_derefval: + DELEGATE(DbgDerefValueInst); case Intrinsic::dbg_label: DELEGATE(DbgLabelInst); case Intrinsic::memcpy: DELEGATE(MemCpyInst); case Intrinsic::memmove: DELEGATE(MemMoveInst); Index: llvm/include/llvm/IR/IntrinsicInst.h =================================================================== --- llvm/include/llvm/IR/IntrinsicInst.h +++ llvm/include/llvm/IR/IntrinsicInst.h @@ -72,6 +72,7 @@ switch (I->getIntrinsicID()) { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: case Intrinsic::dbg_addr: case Intrinsic::dbg_label: return true; @@ -92,10 +93,13 @@ /// variable's value or its address. Value *getVariableLocation(bool AllowNullOp = true) const; + Value *getDerefVariable(bool AllowNullOp = true) const; + /// Does this describe the address of a local variable. True for dbg.addr /// and dbg.declare, but not dbg.value, which describes its value. bool isAddressOfVariable() const { - return getIntrinsicID() != Intrinsic::dbg_value; + return getIntrinsicID() == Intrinsic::dbg_declare || + getIntrinsicID() == Intrinsic::dbg_addr; } DILocalVariable *getVariable() const { @@ -124,6 +128,7 @@ switch (I->getIntrinsicID()) { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: case Intrinsic::dbg_addr: return true; default: return false; @@ -184,6 +189,24 @@ /// @} }; + /// This represents the llvm.dbg.deref.value instruction. + class DbgDerefValueInst : public DbgVariableIntrinsic { + public: + Value *getValue() const { + return getDerefVariable(/* AllowNullOp = */ false); + } + + /// \name Casting methods + /// @{ + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_derefval; + } + static bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + /// @} + }; + /// This represents the llvm.dbg.label instruction. class DbgLabelInst : public DbgInfoIntrinsic { public: Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -803,6 +803,10 @@ [llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty]>; + def int_dbg_derefval : Intrinsic<[], + [llvm_metadata_ty, + llvm_metadata_ty, + llvm_metadata_ty]>; def int_dbg_addr : Intrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, Index: llvm/lib/Analysis/MemorySSA.cpp =================================================================== --- llvm/lib/Analysis/MemorySSA.cpp +++ llvm/lib/Analysis/MemorySSA.cpp @@ -290,6 +290,7 @@ case Intrinsic::dbg_declare: case Intrinsic::dbg_label: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: llvm_unreachable("debuginfo shouldn't have associated defs!"); default: break; Index: llvm/lib/Analysis/ObjCARCInstKind.cpp =================================================================== --- llvm/lib/Analysis/ObjCARCInstKind.cpp +++ llvm/lib/Analysis/ObjCARCInstKind.cpp @@ -184,6 +184,7 @@ // Don't let dbg info affect our results. case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: case Intrinsic::dbg_label: // Short cut: Some intrinsics obviously don't use ObjC pointers. return true; Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -510,6 +510,7 @@ case Intrinsic::sideeffect: case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: case Intrinsic::dbg_label: case Intrinsic::invariant_start: case Intrinsic::invariant_end: Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -883,6 +883,8 @@ auto Op = MI->getOperand(0); OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; return true; + } else if (MI->getOperand(0).isMetadata()) { + OS << MI->getOperand(0).getMetadata(); } else { unsigned Reg; if (MI->getOperand(0).isReg()) { Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1397,6 +1397,22 @@ } return true; } + case Intrinsic::dbg_derefval: { + // This form of DBG_VALUE is target-independent. + const DbgDerefValueInst &DI = cast(CI); + const Value *V = DI.getValue(); + assert(DI.getVariable()->isValidLocationForIntrinsic( + MIRBuilder.getDebugLoc()) && + "Expected inlined-at fields to agree"); + if (!V) { + // Currently the optimizer can produce this; insert an undef to + // help debugging. Probably the optimizer should not do this. + MIRBuilder.buildDirectDbgValue(0, DI.getVariable(), DI.getExpression()); + } else { + MIRBuilder.buildDerefDbgValue(V, DI.getVariable(), DI.getExpression()); + } + return true; + } case Intrinsic::uadd_with_overflow: return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDO, MIRBuilder); case Intrinsic::sadd_with_overflow: Index: llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -159,6 +159,34 @@ return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr); } +MachineInstrBuilder MachineIRBuilder::buildDerefDbgValue(const Value *Derefval, + const MDNode *Variable, + const MDNode *Expr) { + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + assert( + cast(Variable)->isValidLocationForIntrinsic(getDL()) && + "Expected inlined-at fields to agree"); + auto MIB = buildInstr(TargetOpcode::DBG_VALUE); + if (const auto *MDV = dyn_cast(Derefval)) { + if (const auto *LDV = dyn_cast(MDV->getMetadata())) { + MIB.addImplicitPtrMetadata(LDV); + } + } else if (auto *CI = dyn_cast(Derefval)) { + if (CI->getBitWidth() > 64) + MIB.addCImm(CI); + else + MIB.addImm(CI->getZExtValue()); + } else if (auto *CFP = dyn_cast(Derefval)) { + MIB.addFPImm(CFP); + } else { + // Insert %noreg if we didn't find a usable constant and had to drop it. + MIB.addReg(0U); + } + + return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr); +} + MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) { assert(isa(Label) && "not a label"); assert(cast(Label)->isValidLocationForIntrinsic(State.DL) && Index: llvm/lib/CodeGen/LiveDebugValues.cpp =================================================================== --- llvm/lib/CodeGen/LiveDebugValues.cpp +++ llvm/lib/CodeGen/LiveDebugValues.cpp @@ -174,7 +174,8 @@ ImmediateKind, EntryValueKind, EntryValueBackupKind, - EntryValueCopyBackupKind + EntryValueCopyBackupKind, + ImplicitPtrKind } Kind = InvalidKind; /// The value location. Stored separately to avoid repeatedly @@ -186,6 +187,7 @@ int64_t Immediate; const ConstantFP *FPImm; const ConstantInt *CImm; + const DIVariable *ImplicitPtr; } Loc; VarLoc(const MachineInstr &MI, LexicalScopes &LS) @@ -208,6 +210,9 @@ } else if (MI.getOperand(0).isCImm()) { Kind = ImmediateKind; Loc.CImm = MI.getOperand(0).getCImm(); + } else if (MI.getOperand(0).isMetadata()) { + Kind = ImplicitPtrKind; + Loc.ImplicitPtr = MI.getDebugImplicitVariable(); } // We create the debug entry values from the factory functions rather than @@ -314,6 +319,10 @@ MachineOperand MO = MI.getOperand(0); return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr); } + case ImplicitPtrKind: { + MachineOperand MO = MI.getOperand(0); + return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr); + } case EntryValueBackupKind: case EntryValueCopyBackupKind: case InvalidKind: @@ -377,6 +386,9 @@ case ImmediateKind: dbgs() << Loc.Immediate; break; + case ImplicitPtrKind: + dbgs() << Loc.ImplicitPtr->getName(); + break; case InvalidKind: llvm_unreachable("Invalid VarLoc in dump method"); } @@ -803,7 +815,8 @@ unsigned ID; if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() || - MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) { + MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm() || + MI.getOperand(0).isMetadata()) { // Use normal VarLoc constructor for registers and immediates. VarLoc VL(MI, LS); // End all previous ranges of VL.Var. Index: llvm/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/lib/CodeGen/MachineInstr.cpp +++ llvm/lib/CodeGen/MachineInstr.cpp @@ -818,6 +818,11 @@ return cast(getOperand(2).getMetadata()); } +const DIVariable *MachineInstr::getDebugImplicitVariable() const { + assert(isDebugValue() && "not a DBG_VALUE"); + return cast(getOperand(0).getMetadata()); +} + const DIExpression *MachineInstr::getDebugExpression() const { assert(isDebugValue() && "not a DBG_VALUE"); return cast(getOperand(3).getMetadata()); Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1401,11 +1401,13 @@ } return true; } - case Intrinsic::dbg_value: { + case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: { // This form of DBG_VALUE is target-independent. - const DbgValueInst *DI = cast(II); + const DbgVariableIntrinsic *DI = cast(II); const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); - const Value *V = DI->getValue(); + const Value *V = DbgValueInst::classof(DI) ? DI->getVariableLocation(false) + : DI->getDerefVariable(false); assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) && "Expected inlined-at fields to agree"); if (!V) { @@ -1437,6 +1439,15 @@ bool IsIndirect = false; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg, DI->getVariable(), DI->getExpression()); + } else if (DbgDerefValueInst::classof(DI)) { + if (const auto *MDV = dyn_cast(V)) + if (const auto *LDV = dyn_cast(MDV->getMetadata())) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II) + .addImplicitPtrMetadata(LDV) + .addReg(0U) + .addMetadata(DI->getVariable()) + .addMetadata(DI->getExpression()); + } } else { // We can't yet handle anything else here because it would require // generating code, thus altering codegen because of debug info. Index: llvm/lib/IR/DIBuilder.cpp =================================================================== --- llvm/lib/IR/DIBuilder.cpp +++ llvm/lib/IR/DIBuilder.cpp @@ -33,7 +33,7 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU) : M(m), VMContext(M.getContext()), CUNode(CU), - DeclareFn(nullptr), ValueFn(nullptr), LabelFn(nullptr), + DeclareFn(nullptr), ValueFn(nullptr), DerefvalFn(nullptr), LabelFn(nullptr), AllowUnresolvedNodes(AllowUnresolvedNodes) {} void DIBuilder::trackIfUnresolved(MDNode *N) { @@ -887,6 +887,22 @@ InsertBefore); } +Instruction *DIBuilder::insertDbgDerefValueIntrinsic( + Value *V, DILocalVariable *VarInfo, DIExpression *Expr, + const DILocation *DL, Instruction *InsertBefore) { + return insertDbgDerefValueIntrinsic( + V, VarInfo, Expr, DL, InsertBefore ? InsertBefore->getParent() : nullptr, + InsertBefore); +} + +Instruction *DIBuilder::insertDbgDerefValueIntrinsic( + DIVariable *V, DILocalVariable *VarInfo, DIExpression *Expr, + const DILocation *DL, Instruction *InsertBefore) { + return insertDbgDerefValueIntrinsic( + V, VarInfo, Expr, DL, InsertBefore ? InsertBefore->getParent() : nullptr, + InsertBefore); +} + Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, DILocalVariable *VarInfo, DIExpression *Expr, @@ -962,6 +978,48 @@ return B.CreateCall(ValueFn, Args); } +Instruction *DIBuilder::insertDbgDerefValueIntrinsic( + Value *V, DILocalVariable *VarInfo, DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) { + assert(V && "no value passed to dbg.derefval"); + assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.derefval"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); + if (!DerefvalFn) + DerefvalFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_derefval); + + trackIfUnresolved(VarInfo); + trackIfUnresolved(Expr); + Value *Args[] = {V, MetadataAsValue::get(VMContext, VarInfo), + MetadataAsValue::get(VMContext, Expr)}; + + IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore); + return B.CreateCall(DerefvalFn, Args); +} + +Instruction *DIBuilder::insertDbgDerefValueIntrinsic( + DIVariable *V, DILocalVariable *VarInfo, DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) { + assert(V && "no value passed to dbg.derefval"); + assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.derefval"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); + if (!DerefvalFn) + DerefvalFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_derefval); + + trackIfUnresolved(VarInfo); + trackIfUnresolved(Expr); + Value *Args[] = {MetadataAsValue::get(VMContext, V), MetadataAsValue::get(VMContext, VarInfo), + MetadataAsValue::get(VMContext, Expr)}; + + IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore); + return B.CreateCall(DerefvalFn, Args); +} + Instruction *DIBuilder::insertLabel( DILabel *LabelInfo, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) { Index: llvm/lib/IR/IntrinsicInst.cpp =================================================================== --- llvm/lib/IR/IntrinsicInst.cpp +++ llvm/lib/IR/IntrinsicInst.cpp @@ -50,6 +50,14 @@ return nullptr; } +Value *DbgVariableIntrinsic::getDerefVariable(bool AllowNullOp) const { + Value *Op = getArgOperand(0); + if (AllowNullOp && !Op) + return nullptr; + + return Op; +} + Optional DbgVariableIntrinsic::getFragmentSizeInBits() const { if (auto Fragment = getExpression()->getFragmentInfo()) return Fragment->SizeInBits; Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -4322,6 +4322,9 @@ case Intrinsic::dbg_value: // llvm.dbg.value visitDbgIntrinsic("value", cast(Call)); break; + case Intrinsic::dbg_derefval: // llvm.dbg.derefval + visitDbgIntrinsic("derefval", cast(Call)); + break; case Intrinsic::dbg_label: // llvm.dbg.label visitDbgLabelIntrinsic("label", cast(Call)); break; @@ -4877,8 +4880,9 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { auto *MD = cast(DII.getArgOperand(0))->getMetadata(); AssertDI(isa(MD) || - (isa(MD) && !cast(MD)->getNumOperands()), - "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); + (isa(MD) && !cast(MD)->getNumOperands()) || + isa(DII), + "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); AssertDI(isa(DII.getRawVariable()), "invalid llvm.dbg." + Kind + " intrinsic variable", &DII, DII.getRawVariable()); Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -385,6 +385,11 @@ return false; return true; } + if (DbgDerefValueInst *DVI = dyn_cast(I)) { + if (DVI->getDerefVariable()) + return false; + return true; + } if (DbgLabelInst *DLI = dyn_cast(I)) { if (DLI->getLabel()) return false; Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4010,6 +4010,7 @@ switch (IntrinsicID) { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_derefval: case Intrinsic::dbg_label: case Intrinsic::lifetime_end: break; Index: polly/lib/Support/ScopHelper.cpp =================================================================== --- polly/lib/Support/ScopHelper.cpp +++ polly/lib/Support/ScopHelper.cpp @@ -624,6 +624,7 @@ case llvm::Intrinsic::assume: // Some debug info intrinsics are supported/ignored. case llvm::Intrinsic::dbg_value: + case llvm::Intrinsic::dbg_derefval: case llvm::Intrinsic::dbg_declare: return true; default: