diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -3253,6 +3253,83 @@ } }; +/// Storage for identifying a potentially inlined instance of a variable, +/// or a fragment thereof. +class DebugVariable { + using FragmentInfo = DIExpression::FragmentInfo; + using OptFragmentInfo = Optional; + + const DILocalVariable *Variable; + OptFragmentInfo Fragment; + const DILocation *InlinedAt; + + /// Fragment that will overlap all other fragments. Used as default when + /// caller demands a fragment. + static const FragmentInfo DefaultFragment; + +public: + DebugVariable(const DILocalVariable *Var, OptFragmentInfo &&FragmentInfo, + const DILocation *InlinedAt) + : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} + + DebugVariable(const DILocalVariable *Var, OptFragmentInfo &FragmentInfo, + const DILocation *InlinedAt) + : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} + + DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, + const DILocation *InlinedAt) + : DebugVariable(Var, DIExpr->getFragmentInfo(), InlinedAt) {} + + const DILocalVariable *getVar() const { return Variable; } + const OptFragmentInfo &getFragment() const { return Fragment; } + const DILocation *getInlinedAt() const { return InlinedAt; } + + const FragmentInfo getFragmentDefault() const { + return Fragment.getValueOr(DefaultFragment); + } + + static bool isFragmentDefault(const FragmentInfo &F) { + return F == DefaultFragment; + } + + bool operator==(const DebugVariable &Other) const { + return std::tie(Variable, Fragment, InlinedAt) == + std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); + } + + bool operator<(const DebugVariable &Other) const { + return std::tie(Variable, Fragment, InlinedAt) < + std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); + } +}; + +template <> struct DenseMapInfo { + using DV = DebugVariable; + using OptFragmentInfo = Optional; + using FragmentInfo = DIExpression::FragmentInfo; + + // Empty key: no key should be generated that has no DILocalVariable. + static inline DV getEmptyKey() { + return DV(nullptr, OptFragmentInfo(), nullptr); + } + + // Difference in tombstone is that the Optional is meaningful + static inline DV getTombstoneKey() { + return DV(nullptr, OptFragmentInfo({0, 0}), nullptr); + } + + static unsigned getHashValue(const DV &D) { + unsigned HV = 0; + const OptFragmentInfo &Fragment = D.getFragment(); + if (Fragment) + HV = DenseMapInfo::getHashValue(*Fragment); + + return hash_combine(D.getVar(), HV, D.getInlinedAt()); + } + + static bool isEqual(const DV &A, const DV &B) { return A == B; } +}; + } // end namespace llvm #undef DEFINE_MDNODE_GET_UNPACK_IMPL diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h --- a/llvm/include/llvm/Transforms/Utils/Local.h +++ b/llvm/include/llvm/Transforms/Utils/Local.h @@ -178,6 +178,8 @@ /// Returns true if the dbg values have been changed. bool replaceDbgUsesWithUndef(Instruction *I); +void setDbgVariableUndef(DbgVariableIntrinsic* DVI); + //===----------------------------------------------------------------------===// // Control Flow Graph Restructuring. // diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -802,6 +802,9 @@ } void ValueEnumerator::EnumerateValue(const Value *V) { + if (V->getType()->isVoidTy()) { + throw 0; + } assert(!V->getType()->isVoidTy() && "Can't insert void values!"); assert(!isa(V) && "EnumerateValue doesn't handle Metadata!"); diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues.cpp @@ -144,60 +144,6 @@ using FragmentInfo = DIExpression::FragmentInfo; using OptFragmentInfo = Optional; - /// Storage for identifying a potentially inlined instance of a variable, - /// or a fragment thereof. - class DebugVariable { - const DILocalVariable *Variable; - OptFragmentInfo Fragment; - const DILocation *InlinedAt; - - /// Fragment that will overlap all other fragments. Used as default when - /// caller demands a fragment. - static const FragmentInfo DefaultFragment; - - public: - DebugVariable(const DILocalVariable *Var, OptFragmentInfo &&FragmentInfo, - const DILocation *InlinedAt) - : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} - - DebugVariable(const DILocalVariable *Var, OptFragmentInfo &FragmentInfo, - const DILocation *InlinedAt) - : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} - - DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, - const DILocation *InlinedAt) - : DebugVariable(Var, DIExpr->getFragmentInfo(), InlinedAt) {} - - DebugVariable(const MachineInstr &MI) - : DebugVariable(MI.getDebugVariable(), - MI.getDebugExpression()->getFragmentInfo(), - MI.getDebugLoc()->getInlinedAt()) {} - - const DILocalVariable *getVar() const { return Variable; } - const OptFragmentInfo &getFragment() const { return Fragment; } - const DILocation *getInlinedAt() const { return InlinedAt; } - - const FragmentInfo getFragmentDefault() const { - return Fragment.getValueOr(DefaultFragment); - } - - static bool isFragmentDefault(FragmentInfo &F) { - return F == DefaultFragment; - } - - bool operator==(const DebugVariable &Other) const { - return std::tie(Variable, Fragment, InlinedAt) == - std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); - } - - bool operator<(const DebugVariable &Other) const { - return std::tie(Variable, Fragment, InlinedAt) < - std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); - } - }; - - friend struct llvm::DenseMapInfo; - /// A pair of debug variable and value location. struct VarLoc { // The location at which a spilled variable resides. It consists of a @@ -241,8 +187,9 @@ } Loc; VarLoc(const MachineInstr &MI, LexicalScopes &LS) - : Var(MI), Expr(MI.getDebugExpression()), MI(MI), - UVS(MI.getDebugLoc(), LS) { + : Var(MI.getDebugVariable(), MI.getDebugExpression(), + MI.getDebugLoc()->getInlinedAt()), + Expr(MI.getDebugExpression()), MI(MI), UVS(MI.getDebugLoc(), LS) { static_assert((sizeof(Loc) == sizeof(uint64_t)), "hash does not cover all members of Loc"); assert(MI.isDebugValue() && "not a DBG_VALUE"); @@ -559,46 +506,10 @@ } // end anonymous namespace -namespace llvm { - -template <> struct DenseMapInfo { - using DV = LiveDebugValues::DebugVariable; - using OptFragmentInfo = LiveDebugValues::OptFragmentInfo; - using FragmentInfo = LiveDebugValues::FragmentInfo; - - // Empty key: no key should be generated that has no DILocalVariable. - static inline DV getEmptyKey() { - return DV(nullptr, OptFragmentInfo(), nullptr); - } - - // Difference in tombstone is that the Optional is meaningful - static inline DV getTombstoneKey() { - return DV(nullptr, OptFragmentInfo({0, 0}), nullptr); - } - - static unsigned getHashValue(const DV &D) { - unsigned HV = 0; - const OptFragmentInfo &Fragment = D.getFragment(); - if (Fragment) - HV = DenseMapInfo::getHashValue(*Fragment); - - return hash_combine(D.getVar(), HV, D.getInlinedAt()); - } - - static bool isEqual(const DV &A, const DV &B) { return A == B; } -}; - -} // namespace llvm - //===----------------------------------------------------------------------===// // Implementation //===----------------------------------------------------------------------===// -const DIExpression::FragmentInfo - LiveDebugValues::DebugVariable::DefaultFragment = { - std::numeric_limits::max(), - std::numeric_limits::min()}; - char LiveDebugValues::ID = 0; char &llvm::LiveDebugValuesID = LiveDebugValues::ID; @@ -773,7 +684,9 @@ unsigned LocId = VarLocIDs.insert(VL); // Close this variable's previous location range. - DebugVariable V(*DebugInstr); + DebugVariable V(DebugInstr->getDebugVariable(), + DebugInstr->getDebugExpression(), + DebugInstr->getDebugLoc()->getInlinedAt()); OpenRanges.erase(V); // Record the new location as an open range, and a postponed transfer @@ -1099,7 +1012,8 @@ void LiveDebugValues::accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments, OverlapMap &OverlappingFragments) { - DebugVariable MIVar(MI); + DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(), + MI.getDebugLoc()->getInlinedAt()); FragmentInfo ThisFragment = MIVar.getFragmentDefault(); // If this is the first sighting of this variable, then we are guaranteed diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -23,6 +23,9 @@ using namespace llvm; +const DIExpression::FragmentInfo DebugVariable::DefaultFragment = { + std::numeric_limits::max(), std::numeric_limits::min()}; + DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Column, ArrayRef MDs, bool ImplicitCode) diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -485,15 +485,18 @@ I.eraseFromParent(); } } +void llvm::setDbgVariableUndef(DbgVariableIntrinsic *DVI) { + Value *Undef = UndefValue::get(DVI->getType()); + DVI->setOperand( + 0, MetadataAsValue::get(DVI->getContext(), ValueAsMetadata::get(Undef))); +} + bool llvm::replaceDbgUsesWithUndef(Instruction *I) { SmallVector DbgUsers; findDbgUsers(DbgUsers, I); - for (auto *DII : DbgUsers) { - Value *Undef = UndefValue::get(I->getType()); - DII->setOperand(0, MetadataAsValue::get(DII->getContext(), - ValueAsMetadata::get(Undef))); - } + for (auto *DII : DbgUsers) + setDbgVariableUndef(DII); return !DbgUsers.empty(); } @@ -1040,6 +1043,18 @@ assert(PN->use_empty() && "There shouldn't be any uses here!"); PN->eraseFromParent(); } + // If Succ has multiple predecessors, each debug intrinsic in BB may or may + // not be valid when we reach Succ, so the debug variable should be set + // undef since its value is unknown. + while (DbgInfoIntrinsic *DI = dyn_cast(&BB->front())) { + if (auto DVI = cast(DI)) { + setDbgVariableUndef(DVI); + DVI->moveBefore(Succ->getFirstNonPHI()); + } + else { + break; + } + } } // If the unconditional branch we replaced contains llvm.loop metadata, we diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetOperations.h" @@ -38,6 +39,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" @@ -1250,14 +1252,40 @@ Instruction *I1 = &*BB1_Itr++, *I2 = &*BB2_Itr++; // Skip debug info if it is not identical. - DbgInfoIntrinsic *DBI1 = dyn_cast(I1); - DbgInfoIntrinsic *DBI2 = dyn_cast(I2); - if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { - while (isa(I1)) - I1 = &*BB1_Itr++; - while (isa(I2)) - I2 = &*BB2_Itr++; - } + + // If the terminator instruction is hoisted, and any variable locations have + // non-identical debug intrinsics, then those variable locations must be set + // as undef. + // FIXME: If each block contains identical debug variable intrinsics in a + // different order, they will be considered non-identical and be dropped. + MapVector UndefDVIs; + + auto SkipNonIdenticalDbgInfo = + [&BB1_Itr, &BB2_Itr, &UndefDVIs](Instruction *&I1, Instruction *&I2) { + DbgInfoIntrinsic *DBI1 = dyn_cast(I1); + DbgInfoIntrinsic *DBI2 = dyn_cast(I2); + if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { + while (isa(I1)) { + if (DbgVariableIntrinsic *DVI = dyn_cast(I1)) + UndefDVIs.insert( + {DebugVariable(DVI->getVariable(), DVI->getExpression(), + DVI->getDebugLoc()->getInlinedAt()), + DVI}); + I1 = &*BB1_Itr++; + } + while (isa(I2)) { + if (DbgVariableIntrinsic *DVI = dyn_cast(I2)) + UndefDVIs.insert( + {DebugVariable(DVI->getVariable(), DVI->getExpression(), + DVI->getDebugLoc()->getInlinedAt()), + DVI}); + I2 = &*BB2_Itr++; + } + } + }; + + SkipNonIdenticalDbgInfo(I1, I2); + // FIXME: Can we define a safety predicate for CallBr? if (isa(I1) || !I1->isIdenticalToWhenDefined(I2) || (isa(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2)) || @@ -1330,15 +1358,7 @@ I1 = &*BB1_Itr++; I2 = &*BB2_Itr++; - // Skip debug info if it is not identical. - DbgInfoIntrinsic *DBI1 = dyn_cast(I1); - DbgInfoIntrinsic *DBI2 = dyn_cast(I2); - if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { - while (isa(I1)) - I1 = &*BB1_Itr++; - while (isa(I2)) - I2 = &*BB2_Itr++; - } + SkipNonIdenticalDbgInfo(I1, I2); } while (I1->isIdenticalToWhenDefined(I2)); return true; @@ -1374,6 +1394,13 @@ } // Okay, it is safe to hoist the terminator. + for (auto DIVariableInst : UndefDVIs) { + DbgVariableIntrinsic *DVI = DIVariableInst.second; + DVI->moveBefore(BI); + if (Value *V = DVI->getVariableLocation()) + setDbgVariableUndef(DVI); + } + Instruction *NT = I1->clone(); BIParent->getInstList().insert(BI->getIterator(), NT); if (!NT->getType()->isVoidTy()) {