diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -30,6 +30,7 @@ namespace LiveDebugValues { class MLocTracker; +class DbgOpIDMap; using namespace llvm; @@ -168,6 +169,40 @@ static ValueIDNum TombstoneValue; }; +} // End namespace LiveDebugValues + +namespace llvm { +using namespace LiveDebugValues; + +template <> struct DenseMapInfo { + static inline LocIdx getEmptyKey() { return LocIdx::MakeIllegalLoc(); } + static inline LocIdx getTombstoneKey() { return LocIdx::MakeTombstoneLoc(); } + + static unsigned getHashValue(const LocIdx &Loc) { return Loc.asU64(); } + + static bool isEqual(const LocIdx &A, const LocIdx &B) { return A == B; } +}; + +template <> struct DenseMapInfo { + static inline ValueIDNum getEmptyKey() { return ValueIDNum::EmptyValue; } + static inline ValueIDNum getTombstoneKey() { + return ValueIDNum::TombstoneValue; + } + + static unsigned getHashValue(const ValueIDNum &Val) { + return hash_value(Val.asU64()); + } + + static bool isEqual(const ValueIDNum &A, const ValueIDNum &B) { + return A == B; + } +}; + +} // end namespace llvm + +namespace LiveDebugValues { +using namespace llvm; + /// Type for a table of values in a block. using ValueTable = std::unique_ptr; @@ -230,19 +265,181 @@ bool IsVariadic; }; -/// Class recording the (high level) _value_ of a variable. Identifies either -/// the value of the variable as a ValueIDNum, or a constant MachineOperand. +/// TODO: Might pack better if we changed this to a Struct of Arrays, since +/// MachineOperand is width 32, making this struct width 33. We could also +/// potentially avoid storing the whole MachineOperand (sizeof=32), instead +/// choosing to store just the contents portion (sizeof=8) and a Kind enum, +/// since we already know it is some type of immediate value. +/// Stores a single debug operand, which can either be a MachineOperand for +/// directly storing immediate values, or a ValueIDNum representing some value +/// computed at some point in the program. IsConst is used as a discriminator. +struct DbgOp { + union { + ValueIDNum ID; + MachineOperand MO; + }; + bool IsConst; + + DbgOp() : ID(ValueIDNum::EmptyValue), IsConst(false) {} + DbgOp(ValueIDNum ID) : ID(ID), IsConst(false) {} + DbgOp(MachineOperand MO) : MO(MO), IsConst(true) {} + + bool isUndef() const { return !IsConst && ID == ValueIDNum::EmptyValue; } + +#ifndef NDEBUG + void dump(const MLocTracker *MTrack) const; +#endif +}; + +/// A DbgOp whose ID (if any) has resolved to an actual location, LocIdx. Used +/// when working with concrete debug values, i.e. when joining MLocs and VLocs +/// in the TransferTracker or emitting DBG_VALUE/DBG_VALUE_LIST instructions in +/// the MLocTracker. +struct ResolvedDbgOp { + union { + LocIdx Loc; + MachineOperand MO; + }; + bool IsConst; + + ResolvedDbgOp(LocIdx Loc) : Loc(Loc), IsConst(false) {} + ResolvedDbgOp(MachineOperand MO) : MO(MO), IsConst(true) {} + + bool operator==(const ResolvedDbgOp &Other) const { + if (IsConst != Other.IsConst) + return false; + if (IsConst) + return MO.isIdenticalTo(Other.MO); + return Loc == Other.Loc; + } + +#ifndef NDEBUG + void dump(const MLocTracker *MTrack) const; +#endif +}; + +/// An ID used in the DbgOpIDMap (below) to lookup a stored DbgOp. This is used +/// in place of actual DbgOps inside of a DbgValue to reduce its size, as +/// DbgValue is very frequently used and passed around, and the actual DbgOp is +/// over 8x larger than this class, due to storing a MachineOperand. This ID +/// should be equal for all equal DbgOps, and also encodes whether the mapped +/// DbgOp is a constant, meaning that for simple equality or const-ness checks +/// it is not necessary to lookup this ID. +struct DbgOpID { + union { + struct { + uint32_t IsConst : 1; + uint32_t Index : 31; + } ID; + uint32_t RawID; + }; + + DbgOpID() : RawID(UndefID.RawID) { + static_assert(sizeof(DbgOpID) == 4, "DbgOpID should fit within 4 bytes."); + } + DbgOpID(uint32_t RawID) : RawID(RawID) {} + DbgOpID(bool IsConst, uint32_t Index) : ID({IsConst, Index}) {} + + static DbgOpID UndefID; + + bool operator==(const DbgOpID &Other) const { return RawID == Other.RawID; } + bool operator!=(const DbgOpID &Other) const { return !(*this == Other); } + + uint32_t asU32() const { return RawID; } + + bool isUndef() const { return *this == UndefID; } + bool isConst() const { return ID.IsConst && !isUndef(); } + uint32_t getIndex() const { return ID.Index; } + +#ifndef NDEBUG + void dump(const MLocTracker *MTrack, const DbgOpIDMap *OpStore) const; +#endif +}; + +/// Class storing the complete set of values that are observed by DbgValues +/// within the current function. Allows 2-way lookup, with `find` returning the +/// Op for a given ID and `insert` returning the ID for a given Op (creating one +/// if none exists). +class DbgOpIDMap { + + SmallVector ValueOps; + SmallVector ConstOps; + + DenseMap ValueOpToID; + DenseMap ConstOpToID; + +public: + /// If \p Op does not already exist in this map, it is inserted and the + /// corresponding DbgOpID is returned. If Op already exists in this map, then + /// no change is made and the existing ID for Op is returned. + /// Calling this with the undef DbgOp will always return DbgOpID::UndefID. + DbgOpID insert(DbgOp Op) { + if (Op.isUndef()) + return DbgOpID::UndefID; + if (Op.IsConst) + return insertConstOp(Op.MO); + return insertValueOp(Op.ID); + } + /// Returns the DbgOp associated with \p ID. Should only be used for IDs + /// returned from calling `insert` from this map or DbgOpID::UndefID. + DbgOp find(DbgOpID ID) const { + if (ID == DbgOpID::UndefID) + return DbgOp(); + if (ID.isConst()) + return DbgOp(ConstOps[ID.getIndex()]); + return DbgOp(ValueOps[ID.getIndex()]); + } + + void clear() { + ValueOps.clear(); + ConstOps.clear(); + ValueOpToID.clear(); + ConstOpToID.clear(); + } + +private: + DbgOpID insertConstOp(MachineOperand &MO) { + auto ExistingIt = ConstOpToID.find(MO); + if (ExistingIt != ConstOpToID.end()) + return ExistingIt->second; + DbgOpID ID(true, ConstOps.size()); + ConstOpToID.insert(std::make_pair(MO, ID)); + ConstOps.push_back(MO); + return ID; + } + DbgOpID insertValueOp(ValueIDNum VID) { + auto ExistingIt = ValueOpToID.find(VID); + if (ExistingIt != ValueOpToID.end()) + return ExistingIt->second; + DbgOpID ID(false, ValueOps.size()); + ValueOpToID.insert(std::make_pair(VID, ID)); + ValueOps.push_back(VID); + return ID; + } +}; + +// We set the maximum number of operands that we will handle to keep DbgValue +// within a reasonable size (64 bytes), as we store and pass a lot of them +// around. +#define MAX_DBG_OPS 8 + +/// Class recording the (high level) _value_ of a variable. Identifies the value +/// of the variable as a list of ValueIDNums and constant MachineOperands, or as +/// an empty list for undef debug values or VPHI values which we have not found +/// valid locations for. /// This class also stores meta-information about how the value is qualified. /// Used to reason about variable values when performing the second /// (DebugVariable specific) dataflow analysis. class DbgValue { +private: + /// If Kind is Def or VPHI, the set of IDs corresponding to the DbgOps that + /// are used. VPHIs set every ID to EmptyID when we have not found a valid + /// machine-value for every operand, and sets them to the corresponding + /// machine-values when we have found all of them. + DbgOpID DbgOps[MAX_DBG_OPS]; + unsigned OpCount; + public: - /// If Kind is Def, the value number that this value is based on. VPHIs set - /// this field to EmptyValue if there is no machine-value for this VPHI, or - /// the corresponding machine-value if there is one. - ValueIDNum ID; - /// If Kind is Const, the MachineOperand defining this value. - Optional MO; /// For a NoVal or VPHI DbgValue, which block it was generated in. int BlockNo; @@ -251,8 +448,8 @@ typedef enum { Undef, // Represents a DBG_VALUE $noreg in the transfer function only. - Def, // This value is defined by an inst, or is a PHI value. - Const, // A constant value contained in the MachineOperand field. + Def, // This value is defined by some combination of constants, + // instructions, or PHI values. VPHI, // Incoming values to BlockNo differ, those values must be joined by // a PHI in this block. NoVal, // Empty DbgValue indicating an unknown value. Used as initializer, @@ -261,52 +458,113 @@ /// Discriminator for whether this is a constant or an in-program value. KindT Kind; - DbgValue(const ValueIDNum &Val, const DbgValueProperties &Prop, KindT Kind) - : ID(Val), MO(None), BlockNo(0), Properties(Prop), Kind(Kind) { - assert(Kind == Def); + DbgValue(ArrayRef DbgOps, const DbgValueProperties &Prop) + : OpCount(DbgOps.size()), BlockNo(0), Properties(Prop), Kind(Def) { + static_assert(sizeof(DbgValue) <= 64, + "DbgValue should fit within 64 bytes."); + assert(DbgOps.size() == Prop.getLocationOpCount()); + if (DbgOps.size() > MAX_DBG_OPS || + any_of(DbgOps, [](DbgOpID ID) { return ID.isUndef(); })) { + Kind = Undef; + OpCount = 0; +#define DEBUG_TYPE "LiveDebugValues" + if (DbgOps.size() > MAX_DBG_OPS) { + LLVM_DEBUG(dbgs() << "Found DbgValue with more than maximum allowed " + "operands.\n"); + } +#undef DEBUG_TYPE + } else { + for (unsigned Idx = 0; Idx < DbgOps.size(); ++Idx) + this->DbgOps[Idx] = DbgOps[Idx]; + } } DbgValue(unsigned BlockNo, const DbgValueProperties &Prop, KindT Kind) - : ID(ValueIDNum::EmptyValue), MO(None), BlockNo(BlockNo), - Properties(Prop), Kind(Kind) { + : OpCount(0), BlockNo(BlockNo), Properties(Prop), Kind(Kind) { assert(Kind == NoVal || Kind == VPHI); } - DbgValue(const MachineOperand &MO, const DbgValueProperties &Prop, KindT Kind) - : ID(ValueIDNum::EmptyValue), MO(MO), BlockNo(0), Properties(Prop), - Kind(Kind) { - assert(Kind == Const); - } - DbgValue(const DbgValueProperties &Prop, KindT Kind) - : ID(ValueIDNum::EmptyValue), MO(None), BlockNo(0), Properties(Prop), - Kind(Kind) { + : OpCount(0), BlockNo(0), Properties(Prop), Kind(Kind) { assert(Kind == Undef && "Empty DbgValue constructor must pass in Undef kind"); } #ifndef NDEBUG - void dump(const MLocTracker *MTrack) const; + void dump(const MLocTracker *MTrack = nullptr, + const DbgOpIDMap *OpStore = nullptr) const; #endif bool operator==(const DbgValue &Other) const { if (std::tie(Kind, Properties) != std::tie(Other.Kind, Other.Properties)) return false; - else if (Kind == Def && ID != Other.ID) + else if (Kind == Def && !equal(getDbgOpIDs(), Other.getDbgOpIDs())) return false; else if (Kind == NoVal && BlockNo != Other.BlockNo) return false; - else if (Kind == Const) - return MO->isIdenticalTo(*Other.MO); else if (Kind == VPHI && BlockNo != Other.BlockNo) return false; - else if (Kind == VPHI && ID != Other.ID) + else if (Kind == VPHI && !equal(getDbgOpIDs(), Other.getDbgOpIDs())) return false; return true; } bool operator!=(const DbgValue &Other) const { return !(*this == Other); } + + // Returns an array of all the machine values used to calculate this variable + // value, or an empty list for an Undef or unjoined VPHI. + ArrayRef getDbgOpIDs() const { return {DbgOps, OpCount}; } + + // Returns either DbgOps[Index] if this DbgValue has Debug Operands, or + // the ID for ValueIDNum::EmptyValue otherwise (i.e. if this is an Undef, + // NoVal, or an unjoined VPHI). + DbgOpID getDbgOpID(unsigned Index) const { + if (!OpCount) + return DbgOpID::UndefID; + assert(Index < OpCount); + return DbgOps[Index]; + } + // Replaces this DbgValue's existing DbgOpIDs (if any) with the contents of + // \p NewIDs. The number of DbgOpIDs passed must be equal to the number of + // arguments expected by this DbgValue's properties (the return value of + // `getLocationOpCount()`). + void setDbgOpIDs(ArrayRef NewIDs) { + // We can go from no ops to some ops, but not from some ops to no ops. + assert(NewIDs.size() == getLocationOpCount() && + "Incorrect number of Debug Operands for this DbgValue."); + OpCount = NewIDs.size(); + for (unsigned Idx = 0; Idx < NewIDs.size(); ++Idx) + DbgOps[Idx] = NewIDs[Idx]; + } + + // The number of debug operands expected by this DbgValue's expression. + // getDbgOpIDs() should return an array of this length, unless this is an + // Undef or an unjoined VPHI. + unsigned getLocationOpCount() const { + return Properties.getLocationOpCount(); + } + + // Returns true if this or Other are unjoined PHIs, which do not have defined + // Loc Ops, or if the `n`th Loc Op for this has a different constness to the + // `n`th Loc Op for Other. + bool hasJoinableLocOps(const DbgValue &Other) const { + if (isUnjoinedPHI() || Other.isUnjoinedPHI()) + return true; + for (unsigned Idx = 0; Idx < getLocationOpCount(); ++Idx) { + if (getDbgOpID(Idx).isConst() != Other.getDbgOpID(Idx).isConst()) + return false; + } + return true; + } + + bool isUnjoinedPHI() const { return Kind == VPHI && OpCount == 0; } + + bool hasIdenticalValidLocOps(const DbgValue &Other) const { + if (!OpCount) + return false; + return equal(getDbgOpIDs(), Other.getDbgOpIDs()); + } }; class LocIdxToIndexFunctor { @@ -716,29 +974,14 @@ : OverlappingFragments(O), EmptyProperties(EmptyExpr, false, false) {} void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, - Optional ID) { + const SmallVectorImpl &DebugOps) { assert(MI.isDebugValue() || MI.isDebugRef()); + assert(DebugOps.size() <= 1); DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); - DbgValue Rec = (ID) ? DbgValue(*ID, Properties, DbgValue::Def) - : DbgValue(Properties, DbgValue::Undef); - - // Attempt insertion; overwrite if it's already mapped. - auto Result = Vars.insert(std::make_pair(Var, Rec)); - if (!Result.second) - Result.first->second = Rec; - Scopes[Var] = MI.getDebugLoc().get(); - - considerOverlaps(Var, MI.getDebugLoc().get()); - } - - void defVar(const MachineInstr &MI, const MachineOperand &MO) { - // Only DBG_VALUEs can define constant-valued variables. - assert(MI.isDebugValue()); - DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), - MI.getDebugLoc()->getInlinedAt()); - DbgValueProperties Properties(MI); - DbgValue Rec = DbgValue(MO, Properties, DbgValue::Const); + DbgValue Rec = (DebugOps.size() > 0) + ? DbgValue(DebugOps, Properties) + : DbgValue(Properties, DbgValue::Undef); // Attempt insertion; overwrite if it's already mapped. auto Result = Vars.insert(std::make_pair(Var, Rec)); @@ -907,6 +1150,8 @@ /// the result. DenseMap> SeenDbgPHIs; + DbgOpIDMap DbgOpStore; + /// True if we need to examine call instructions for stack clobbers. We /// normally assume that they don't clobber SP, but stack probes on Windows /// do. @@ -1166,33 +1411,4 @@ } // namespace LiveDebugValues -namespace llvm { -using namespace LiveDebugValues; - -template <> struct DenseMapInfo { - static inline LocIdx getEmptyKey() { return LocIdx::MakeIllegalLoc(); } - static inline LocIdx getTombstoneKey() { return LocIdx::MakeTombstoneLoc(); } - - static unsigned getHashValue(const LocIdx &Loc) { return Loc.asU64(); } - - static bool isEqual(const LocIdx &A, const LocIdx &B) { return A == B; } -}; - -template <> struct DenseMapInfo { - static inline ValueIDNum getEmptyKey() { return ValueIDNum::EmptyValue; } - static inline ValueIDNum getTombstoneKey() { - return ValueIDNum::TombstoneValue; - } - - static unsigned getHashValue(const ValueIDNum &Val) { - return hash_value(Val.asU64()); - } - - static bool isEqual(const ValueIDNum &A, const ValueIDNum &B) { - return A == B; - } -}; - -} // end namespace llvm - #endif /* LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_INSTRREFBASEDLDV_H */ diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -155,6 +155,8 @@ cl::desc("livedebugvalues-stack-ws-limit"), cl::init(250)); +DbgOpID DbgOpID::UndefID = DbgOpID(0xffffffff); + /// Tracker for converting machine value locations and variable values into /// variable locations (the output of LiveDebugValues), recorded as DBG_VALUEs /// specifying block live-in locations and transfers within blocks. @@ -259,7 +261,7 @@ /// object fields to track variable locations as we step through the block. /// FIXME: could just examine mloctracker instead of passing in \p mlocs? void - loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, + loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, DbgOpIDMap &DbgOpStore, const SmallVectorImpl> &VLocs, unsigned NumLocs) { ActiveMLocs.clear(); @@ -284,9 +286,13 @@ // Initialized the preferred-location map with illegal locations, to be // filled in later. - for (const auto &VLoc : VLocs) - if (VLoc.second.Kind == DbgValue::Def) - ValueToLoc.insert({VLoc.second.ID, LocIdx::MakeIllegalLoc()}); + for (const auto &VLoc : VLocs) { + if (VLoc.second.Kind == DbgValue::Def && + !VLoc.second.getDbgOpID(0).isConst()) { + ValueToLoc.insert({DbgOpStore.find(VLoc.second.getDbgOpID(0)).ID, + LocIdx::MakeIllegalLoc()}); + } + } ActiveMLocs.reserve(VLocs.size()); ActiveVLocs.reserve(VLocs.size()); @@ -320,14 +326,16 @@ // Now map variables to their picked LocIdxes. for (const auto &Var : VLocs) { - if (Var.second.Kind == DbgValue::Const) { + DbgOpID OpID = Var.second.getDbgOpID(0); + DbgOp Op = DbgOpStore.find(OpID); + if (Var.second.Kind == DbgValue::Def && OpID.isConst()) { PendingDbgValues.push_back( - emitMOLoc(*Var.second.MO, Var.first, Var.second.Properties)); + emitMOLoc(Op.MO, Var.first, Var.second.Properties)); continue; } // If the value has no location, we can't make a variable location. - const ValueIDNum &Num = Var.second.ID; + const ValueIDNum &Num = Op.ID; auto ValuesPreferredLoc = ValueToLoc.find(Num); if (ValuesPreferredLoc->second.isIllegal()) { // If it's a def that occurs in this block, register it as a @@ -674,17 +682,43 @@ ValueIDNum ValueIDNum::TombstoneValue = {UINT_MAX, UINT_MAX, UINT_MAX - 1}; #ifndef NDEBUG -void DbgValue::dump(const MLocTracker *MTrack) const { - if (Kind == Const) { - MO->dump(); - } else if (Kind == NoVal) { - dbgs() << "NoVal(" << BlockNo << ")"; - } else if (Kind == VPHI) { - dbgs() << "VPHI(" << BlockNo << "," << MTrack->IDAsString(ID) << ")"; +void ResolvedDbgOp::dump(const MLocTracker *MTrack) const { + if (IsConst) { + dbgs() << MO; } else { - assert(Kind == Def); + dbgs() << MTrack->LocIdxToName(Loc); + } +} +void DbgOp::dump(const MLocTracker *MTrack) const { + if (IsConst) { + dbgs() << MO; + } else if (!isUndef()) { dbgs() << MTrack->IDAsString(ID); } +} +void DbgOpID::dump(const MLocTracker *MTrack, const DbgOpIDMap *OpStore) const { + if (!OpStore) { + dbgs() << "ID(" << asU32() << ")"; + } else { + OpStore->find(*this).dump(MTrack); + } +} +void DbgValue::dump(const MLocTracker *MTrack, + const DbgOpIDMap *OpStore) const { + if (Kind == NoVal) { + dbgs() << "NoVal(" << BlockNo << ")"; + } else if (Kind == VPHI || Kind == Def) { + if (Kind == VPHI) + dbgs() << "VPHI(" << BlockNo << ","; + else + dbgs() << "Def("; + for (unsigned Idx = 0; Idx < getDbgOpIDs().size(); ++Idx) { + getDbgOpID(Idx).dump(MTrack, OpStore); + if (Idx != 0) + dbgs() << ","; + } + dbgs() << ")"; + } if (Properties.Indirect) dbgs() << " indir"; if (Properties.DIExpr) @@ -1076,8 +1110,9 @@ // contribute to locations in this block, but don't propagate further. // Interpret it like a DBG_VALUE $noreg. if (MI.isDebugValueList()) { + SmallVector EmptyDebugOps; if (VTracker) - VTracker->defVar(MI, Properties, None); + VTracker->defVar(MI, Properties, EmptyDebugOps); if (TTracker) TTracker->redefVar(MI, Properties, None); return true; @@ -1094,16 +1129,21 @@ // locations are already solved, and we report this DBG_VALUE and the value // it refers to to VLocTracker. if (VTracker) { - if (MO.isReg()) { - // Feed defVar the new variable location, or if this is a - // DBG_VALUE $noreg, feed defVar None. - if (MO.getReg()) - VTracker->defVar(MI, Properties, MTracker->readReg(MO.getReg())); - else - VTracker->defVar(MI, Properties, None); - } else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) { - VTracker->defVar(MI, MO); + SmallVector DebugOps; + // Feed defVar the new variable location, or if this is a DBG_VALUE $noreg, + // feed defVar None. + if (!MI.isUndefDebugValue()) { + // There should be no undef registers here, as we've screened for undef + // debug values. + if (MO.isReg()) { + DebugOps.push_back(DbgOpStore.insert(MTracker->readReg(MO.getReg()))); + } else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) { + DebugOps.push_back(DbgOpStore.insert(MO)); + } else { + llvm_unreachable("Unexpected debug operand type."); + } } + VTracker->defVar(MI, Properties, DebugOps); } // If performing final tracking of transfers, report this variable definition @@ -1287,8 +1327,11 @@ // for DBG_INSTR_REFs as DBG_VALUEs (just, the former can refer to values that // aren't immediately available). DbgValueProperties Properties(Expr, false, false); + SmallVector DbgOpIDs; + if (NewID) + DbgOpIDs.push_back(DbgOpStore.insert(*NewID)); if (VTracker) - VTracker->defVar(MI, Properties, NewID); + VTracker->defVar(MI, Properties, DbgOpIDs); // If we're on the final pass through the function, decompose this INSTR_REF // into a plain DBG_VALUE. @@ -1334,6 +1377,7 @@ // FoundLoc is None. // (XXX -- could morph the DBG_INSTR_REF in the future). MachineInstr *DbgMI = MTracker->emitLoc(FoundLoc, V, Properties); + TTracker->PendingDbgValues.push_back(DbgMI); TTracker->flushDbgValues(MI.getIterator(), nullptr); return true; @@ -2397,7 +2441,7 @@ return None; const DbgValue &OutVal = *OutValIt->second; - if (OutVal.Kind == DbgValue::Const || OutVal.Kind == DbgValue::NoVal) + if (OutVal.getDbgOpID(0).isConst() || OutVal.Kind == DbgValue::NoVal) // Consts and no-values cannot have locations we can join on. return None; @@ -2410,8 +2454,8 @@ // present. Do the same for VPHIs where we know the VPHI value. if (OutVal.Kind == DbgValue::Def || (OutVal.Kind == DbgValue::VPHI && OutVal.BlockNo != MBB.getNumber() && - OutVal.ID != ValueIDNum::EmptyValue)) { - ValueIDNum ValToLookFor = OutVal.ID; + !OutVal.getDbgOpID(0).isUndef())) { + ValueIDNum ValToLookFor = DbgOpStore.find(OutVal.getDbgOpID(0)).ID; // Search the live-outs of the predecessor for the specified value. for (unsigned int I = 0; I < NumLocs; ++I) { if (MOutLocs[ThisBBNum][I] == ValToLookFor) @@ -2543,7 +2587,7 @@ return false; if (V.second->Kind == DbgValue::NoVal) return false; - if (V.second->Kind == DbgValue::Const && FirstVal.Kind != DbgValue::Const) + if (!V.second->hasJoinableLocOps(FirstVal)) return false; } @@ -2556,7 +2600,7 @@ // If both values are not equal but have equal non-empty IDs then they refer // to the same value from different sources (e.g. one is VPHI and the other // is Def), which does not cause disagreement. - if (V.second->ID != ValueIDNum::EmptyValue && V.second->ID == FirstVal.ID) + if (V.second->hasIdenticalValidLocOps(FirstVal)) continue; // Eliminate if a backedge feeds a VPHI back into itself. @@ -2807,8 +2851,9 @@ pickVPHILoc(*MBB, Var, LiveOutIdx, MOutLocs, Preds); if (ValueNum) { - InLocsChanged |= LiveIn->ID != *ValueNum; - LiveIn->ID = *ValueNum; + DbgOpID ValueID = DbgOpStore.insert(*ValueNum); + InLocsChanged |= LiveIn->getDbgOpID(0) != ValueID; + LiveIn->setDbgOpIDs(ValueID); } } @@ -2878,8 +2923,7 @@ DbgValue *BlockLiveIn = LiveInIdx[MBB]; if (BlockLiveIn->Kind == DbgValue::NoVal) continue; - if (BlockLiveIn->Kind == DbgValue::VPHI && - BlockLiveIn->ID == ValueIDNum::EmptyValue) + if (BlockLiveIn->isUnjoinedPHI()) continue; if (BlockLiveIn->Kind == DbgValue::VPHI) BlockLiveIn->Kind = DbgValue::Def; @@ -3070,7 +3114,8 @@ // instructions, installing transfers. MTracker->reset(); MTracker->loadFromArray(MInLocs[BBNum], BBNum); - TTracker->loadInlocs(MBB, MInLocs[BBNum], Output[BBNum], NumLocs); + TTracker->loadInlocs(MBB, MInLocs[BBNum], DbgOpStore, Output[BBNum], + NumLocs); CurBB = BBNum; CurInst = 1; @@ -3368,6 +3413,7 @@ OverlapFragments.clear(); SeenFragments.clear(); SeenDbgPHIs.clear(); + DbgOpStore.clear(); return Changed; } diff --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp --- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp +++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp @@ -178,6 +178,13 @@ LDV->VTracker = &*VTracker; } + DbgOpID addValueDbgOp(ValueIDNum V) { + return LDV->DbgOpStore.insert(DbgOp(V)); + } + DbgOpID addConstDbgOp(MachineOperand MO) { + return LDV->DbgOpStore.insert(DbgOp(MO)); + } + // Some routines for bouncing into LDV, void buildMLocValueMap(FuncValueTable &MInLocs, FuncValueTable &MOutLocs, SmallVectorImpl &MLocTransfer) { @@ -1798,6 +1805,10 @@ ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); ValueIDNum RspPHIInBlk2(Br2Blk, 0, RspLoc); ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); + DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); + DbgOpID RspPHIInBlk2ID = addValueDbgOp(RspPHIInBlk2); + DbgOpID RspPHIInBlk3ID = addValueDbgOp(RspPHIInBlk3); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -1820,8 +1831,8 @@ Optional Result; // Simple case: join two distinct values on entry to the block. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRaxID, EmptyProps); Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); // Should have picked a PHI in $rsp in block 3. EXPECT_TRUE(Result); @@ -1839,8 +1850,7 @@ // Swap back, std::swap(VLiveOuts[1], VLiveOuts[2]); // Setting one of these to being a constant should prohibit merging. - VLiveOuts[1].Kind = DbgValue::Const; - VLiveOuts[1].MO = MachineOperand::CreateImm(0); + VLiveOuts[1].setDbgOpIDs(addConstDbgOp(MachineOperand::CreateImm(0))); Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); @@ -1851,7 +1861,7 @@ EXPECT_FALSE(Result); // NoVals shouldn't join with anything else. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::NoVal); Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); @@ -1860,9 +1870,8 @@ // such a scenario: first, where one incoming edge has a VPHI with no known // value. This represents an edge where there was a PHI value that can't be // found in the register file -- we can't subsequently find a PHI here. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); - EXPECT_EQ(VLiveOuts[2].ID, ValueIDNum::EmptyValue); Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); @@ -1870,9 +1879,9 @@ // location. Use a PHI machine-value for doing this, as VPHIs should always // have PHI values, or they should have been eliminated. MOutLocs[2][0] = RspPHIInBlk2; - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); - VLiveOuts[2].ID = RspPHIInBlk2; // Set location where PHI happens. + VLiveOuts[2].setDbgOpIDs(RspPHIInBlk2ID); // Set location where PHI happens. Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { @@ -1889,14 +1898,14 @@ DIExpression *NewExpr = DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); DbgValueProperties PropsWithExpr(NewExpr, false, false); - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithExpr); Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); DbgValueProperties PropsWithIndirect(EmptyExpr, true, false); - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithIndirect); Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); } @@ -1927,6 +1936,10 @@ ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); + DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); + DbgOpID RspPHIInBlk1ID = addValueDbgOp(RspPHIInBlk1); + DbgOpID RaxPHIInBlk1ID = addValueDbgOp(RaxPHIInBlk1); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -1948,8 +1961,8 @@ Optional Result; // See that we can merge as normal on a backedge. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); // Should have picked a PHI in $rsp in block 1. EXPECT_TRUE(Result); @@ -1970,7 +1983,7 @@ MOutLocs[0][1] = LiveInRsp; MOutLocs[1][0] = RaxPHIInBlk1; MOutLocs[1][1] = RaxPHIInBlk1; - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); // Crucially, a VPHI originating in this block: VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); @@ -1988,7 +2001,7 @@ // Additionally, if the VPHI coming back on the loop backedge isn't from // this block (block 1), we can't merge it. MOutLocs[1][1] = RaxPHIInBlk1; - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); @@ -2029,6 +2042,12 @@ ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc); ValueIDNum RbxPHIInBlk1(Loop1Blk, 0, RbxLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); + DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); + DbgOpID LiveInRbxID = addValueDbgOp(LiveInRbx); + DbgOpID RspPHIInBlk1ID = addValueDbgOp(RspPHIInBlk1); + DbgOpID RaxPHIInBlk1ID = addValueDbgOp(RaxPHIInBlk1); + DbgOpID RbxPHIInBlk1ID = addValueDbgOp(RbxPHIInBlk1); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -2055,9 +2074,9 @@ Optional Result; // See that we can merge as normal on a backedge. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRbxID, EmptyProps); Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); // Should have picked a PHI in $rsp in block 1. EXPECT_TRUE(Result); @@ -2084,9 +2103,9 @@ // If the variables value on that edge is a VPHI feeding into itself, that's // fine. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); - VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); + VLiveOuts[2] = DbgValue(LiveInRbxID, EmptyProps); Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { @@ -2095,7 +2114,7 @@ // Likewise: the other backedge being a VPHI from block 1 should be accepted. MOutLocs[2][0] = RspPHIInBlk1; - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); @@ -2154,10 +2173,10 @@ unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3; - ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); - ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); - ValueIDNum RspPHIInBlkBr2Blk(Br2Blk, 0, RspLoc); - ValueIDNum RspPHIInBlkRetBlk(RetBlk, 0, RspLoc); + DbgOpID LiveInRspID = DbgOpID(false, 0); + DbgOpID LiveInRaxID = DbgOpID(false, 1); + DbgOpID RspPHIInBlkBr2BlkID = DbgOpID(false, 2); + DbgOpID RspPHIInBlkRetBlkID = DbgOpID(false, 3); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -2185,12 +2204,12 @@ // vlocJoin is here to propagate incoming values, and eliminate PHIs. Start // off by propagating a value into the merging block, number 3. DbgValue JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal); - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, EmptyProps); bool Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); // Output locs should have changed. EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // And if we did it a second time, leaving the live-ins as it was, then // we should report no change. @@ -2200,15 +2219,15 @@ // If the live-in variable values are different, but there's no PHI placed // in this block, then just pick a location. It should be the first (in RPO) // predecessor to avoid being a backedge. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRaxID, EmptyProps); JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); // RPO is blocks 0 2 1 3, so LiveInRax is picked as the first predecessor // of this join. - EXPECT_EQ(JoinedLoc.ID, LiveInRax); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRaxID); // No tests for whether vlocJoin will pass-through a variable with differing // expressions / properties. Those can only come about due to assignments; and @@ -2224,46 +2243,46 @@ EXPECT_FALSE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); // This should not have been assigned a fixed value. - EXPECT_EQ(JoinedLoc.ID, ValueIDNum::EmptyValue); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), DbgOpID::UndefID); EXPECT_EQ(JoinedLoc.BlockNo, 3); // Try a simple PHI elimination. Put a PHI in block 3, but LiveInRsp on both // incoming edges. Re-load in and out-locs with unrelated values; they're // irrelevant. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, EmptyProps); JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // Try the same PHI elimination but with one incoming value being a VPHI // referring to the same value. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); - VLiveOuts[2].ID = LiveInRsp; + VLiveOuts[2].setDbgOpIDs(LiveInRspID); JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // If the "current" live-in is a VPHI, but not a VPHI generated in the current // block, then it's the remains of an earlier value propagation. We should // value propagate through this merge. Even if the current incoming values // disagree, because we've previously determined any VPHI here is redundant. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRaxID, EmptyProps); JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRax); // from block 2 + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRaxID); // from block 2 // The above test, but test that we will install one value-propagated VPHI // over another. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(0, EmptyProps, DbgValue::VPHI); JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); @@ -2273,8 +2292,8 @@ // We shouldn't eliminate PHIs when properties disagree. DbgValueProperties PropsWithIndirect(EmptyExpr, true, false); - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithIndirect); JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_FALSE(Result); @@ -2284,13 +2303,13 @@ // Even if properties disagree, we should still value-propagate if there's no // PHI to be eliminated. The disagreeing values should work themselves out, // seeing how we've determined no PHI is necessary. - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithIndirect); JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // Also check properties come from block 2, the first RPO predecessor to block // three. EXPECT_EQ(JoinedLoc.Properties, PropsWithIndirect); @@ -2300,11 +2319,30 @@ DIExpression *NewExpr = DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); DbgValueProperties PropsWithExpr(NewExpr, false, false); - VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def); + VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithExpr); JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_FALSE(Result); + + // Try placing a PHI with variadic debug values. With differing input values + // (LiveInRsp, LiveInRax), this PHI should not be eliminated. + DIExpression *TwoOpExpr = + DIExpression::get(Ctx, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, + 1, dwarf::DW_OP_plus}); + DbgValueProperties TwoOpProps(TwoOpExpr, false, true); + DbgOpID Locs0[] = {LiveInRspID, LiveInRaxID}; + DbgOpID Locs1[] = {LiveInRaxID, LiveInRspID}; + JoinedLoc = DbgValue(3, TwoOpProps, DbgValue::VPHI); + VLiveOuts[1] = DbgValue(Locs0, TwoOpProps); + VLiveOuts[2] = DbgValue(Locs1, TwoOpProps); + Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc); + // Expect no change. + EXPECT_FALSE(Result); + EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); + // This should not have been assigned a fixed value. + EXPECT_EQ(JoinedLoc.getDbgOpID(0), DbgOpID::UndefID); + EXPECT_EQ(JoinedLoc.BlockNo, 3); } TEST_F(InstrRefLDVTest, vlocJoinLoops) { @@ -2323,9 +2361,9 @@ unsigned EntryBlk = 0, LoopBlk = 1; - ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); - ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); - ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); + DbgOpID LiveInRspID = DbgOpID(false, 0); + DbgOpID LiveInRaxID = DbgOpID(false, 1); + DbgOpID RspPHIInBlk1ID = DbgOpID(false, 2); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -2354,17 +2392,17 @@ // First: when there's no VPHI placed already, propagate the live-in value of // the first RPO predecessor. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); - DbgValue JoinedLoc = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); + DbgValue JoinedLoc = DbgValue(LiveInRaxID, EmptyProps); bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // If there is a VPHI: don't elimiante it if there are disagreeing values. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_FALSE(Result); @@ -2372,20 +2410,20 @@ EXPECT_EQ(JoinedLoc.BlockNo, 1); // If we feed this VPHI back into itself though, we can eliminate it. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // Don't eliminate backedge VPHIs if the predecessors have different // properties. DIExpression *NewExpr = DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); DbgValueProperties PropsWithExpr(NewExpr, false, false); - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, PropsWithExpr, DbgValue::VPHI); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); @@ -2394,7 +2432,7 @@ EXPECT_EQ(JoinedLoc.BlockNo, 1); // Backedges with VPHIs, but from the wrong block, shouldn't be eliminated. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); @@ -2426,9 +2464,9 @@ unsigned EntryBlk = 0; - ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); - ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); - ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc); + DbgOpID LiveInRspID = DbgOpID(false, 0); + DbgOpID LiveInRaxID = DbgOpID(false, 1); + DbgOpID LiveInRbxID = DbgOpID(false, 2); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -2457,9 +2495,9 @@ AllVars.insert(Var); // Test a normal VPHI isn't eliminated. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); - VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); - VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); + VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); + VLiveOuts[2] = DbgValue(LiveInRbxID, EmptyProps); DbgValue JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_FALSE(Result); @@ -2467,18 +2505,18 @@ EXPECT_EQ(JoinedLoc.BlockNo, 1); // Common VPHIs on backedges should merge. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc); EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); - EXPECT_EQ(JoinedLoc.ID, LiveInRsp); + EXPECT_EQ(JoinedLoc.getDbgOpID(0), LiveInRspID); // They shouldn't merge if one of their properties is different. DbgValueProperties PropsWithIndirect(EmptyExpr, true, false); - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); VLiveOuts[2] = DbgValue(1, PropsWithIndirect, DbgValue::VPHI); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); @@ -2488,7 +2526,7 @@ EXPECT_EQ(JoinedLoc.BlockNo, 1); // VPHIs from different blocks should not merge. - VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); @@ -2513,6 +2551,7 @@ std::tie(MInLocs, MOutLocs) = allocValueTables(1, 2); ValueIDNum LiveInRsp = ValueIDNum(0, 0, RspLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); MInLocs[0][0] = MOutLocs[0][0] = LiveInRsp; DebugVariable Var(FuncVariable, None, nullptr); @@ -2541,7 +2580,7 @@ // If we put an assignment in the transfer function, that should... well, // do nothing, because we don't store the live-outs. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output.size(), 0ul); @@ -2568,6 +2607,9 @@ ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); ValueIDNum RspPHIInBlk3 = ValueIDNum(RetBlk, 0, RspLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); + DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); + DbgOpID RspPHIInBlk3ID = addValueDbgOp(RspPHIInBlk3); FuncValueTable MInLocs, MOutLocs; std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2); @@ -2618,7 +2660,7 @@ // An assignment in the end block should also not affect other blocks; or // produce any live-ins. - VLocs[3].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[3].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2630,7 +2672,7 @@ // Assignments in either of the side-of-diamond blocks should also not be // propagated anywhere. VLocs[3].Vars.clear(); - VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[2].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2640,7 +2682,7 @@ VLocs[2].Vars.clear(); ClearOutputs(); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2652,7 +2694,7 @@ // However: putting an assignment in the first block should propagate variable // values through to all other blocks, as it dominates. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2660,11 +2702,11 @@ ASSERT_EQ(Output[2].size(), 1ul); ASSERT_EQ(Output[3].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); @@ -2672,7 +2714,7 @@ // should still be propagated, as buildVLocValueMap shouldn't care about // what's in the registers (except for PHIs). // values through to all other blocks, as it dominates. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2680,18 +2722,18 @@ ASSERT_EQ(Output[2].size(), 1ul); ASSERT_EQ(Output[3].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRax); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRax); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRax); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); // We should get a live-in to the merging block, if there are two assigns of // the same value in either side of the diamond. - VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[2].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2699,14 +2741,14 @@ EXPECT_EQ(Output[2].size(), 0ul); ASSERT_EQ(Output[3].size(), 1ul); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[1].Vars.clear(); VLocs[2].Vars.clear(); // If we assign a value in the entry block, then 'undef' on a branch, we // shouldn't have a live-in in the merge block. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); @@ -2715,9 +2757,9 @@ ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[3].size(), 0ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2725,8 +2767,8 @@ // Having different values joining into the merge block should mean we have // no live-in in that block. Block ones LiveInRax value doesn't appear as a // live-in anywhere, it's block internal. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2734,9 +2776,9 @@ ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[3].size(), 0ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2744,8 +2786,8 @@ // But on the other hand, if there's a location in the register file where // those two values can be joined, do so. MOutLocs[1][0] = LiveInRax; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2753,11 +2795,11 @@ ASSERT_EQ(Output[2].size(), 1ul); ASSERT_EQ(Output[3].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, RspPHIInBlk3); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), RspPHIInBlk3ID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2785,6 +2827,11 @@ ValueIDNum RspPHIInBlk1 = ValueIDNum(LoopBlk, 0, RspLoc); ValueIDNum RspDefInBlk1 = ValueIDNum(LoopBlk, 1, RspLoc); ValueIDNum RaxPHIInBlk1 = ValueIDNum(LoopBlk, 0, RaxLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); + DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); + DbgOpID RspPHIInBlk1ID = addValueDbgOp(RspPHIInBlk1); + DbgOpID RspDefInBlk1ID = addValueDbgOp(RspDefInBlk1); + DbgOpID RaxPHIInBlk1ID = addValueDbgOp(RaxPHIInBlk1); FuncValueTable MInLocs, MOutLocs; std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2); @@ -2821,22 +2868,22 @@ Output.resize(3); // Easy starter: a dominating assign should propagate to all blocks. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); ASSERT_EQ(Output[1].size(), 1ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); // Put an undef assignment in the loop. Should get no live-in value. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); @@ -2848,32 +2895,32 @@ VLocs[1].Vars.clear(); // Assignment of the same value should naturally join. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); ASSERT_EQ(Output[1].size(), 1ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); // Assignment of different values shouldn't join with no machine PHI vals. // Will be live-in to exit block as it's dominated. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); EXPECT_EQ(Output[1].size(), 0ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRax); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2882,15 +2929,15 @@ // with unrelated assign in loop block again. MInLocs[1][0] = RspPHIInBlk1; MOutLocs[1][0] = RspDefInBlk1; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); EXPECT_EQ(Output[1].size(), 0ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRax); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2899,17 +2946,17 @@ // find the appropriate PHI. MInLocs[1][0] = RspPHIInBlk1; MOutLocs[1][0] = RspDefInBlk1; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1ID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); ASSERT_EQ(Output[1].size(), 1ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), RspPHIInBlk1ID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), RspDefInBlk1ID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2920,17 +2967,17 @@ MOutLocs[1][0] = LiveInRsp; MInLocs[1][1] = RaxPHIInBlk1; MOutLocs[1][1] = RspDefInBlk1; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1ID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); ASSERT_EQ(Output[1].size(), 1ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, RaxPHIInBlk1); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), RaxPHIInBlk1ID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), RspDefInBlk1ID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2942,8 +2989,8 @@ MOutLocs[1][0] = RspDefInBlk1; MInLocs[1][1] = RaxPHIInBlk1; MOutLocs[1][1] = RspDefInBlk1; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1ID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -2951,9 +2998,9 @@ ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); // Today, the first register is picked. - EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), RspPHIInBlk1ID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), RspDefInBlk1ID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2976,17 +3023,17 @@ MOutLocs[1][0] = RspPHIInBlk1; MInLocs[1][1] = LiveInRax; MOutLocs[1][1] = LiveInRax; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(RspPHIInBlk1, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(RspPHIInBlk1ID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); ASSERT_EQ(Output[1].size(), 1ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), RspPHIInBlk1ID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk1); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), RspPHIInBlk1ID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -2995,17 +3042,17 @@ // because there's a def in in. MInLocs[1][0] = LiveInRsp; MOutLocs[1][0] = LiveInRsp; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); ASSERT_EQ(Output[1].size(), 1ul); ASSERT_EQ(Output[2].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -3038,6 +3085,11 @@ ValueIDNum RspPHIInBlk1 = ValueIDNum(Loop1Blk, 0, RspLoc); ValueIDNum RspPHIInBlk2 = ValueIDNum(Loop2Blk, 0, RspLoc); ValueIDNum RspDefInBlk2 = ValueIDNum(Loop2Blk, 1, RspLoc); + DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); + DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); + DbgOpID RspPHIInBlk1ID = addValueDbgOp(RspPHIInBlk1); + DbgOpID RspPHIInBlk2ID = addValueDbgOp(RspPHIInBlk2); + DbgOpID RspDefInBlk2ID = addValueDbgOp(RspDefInBlk2); FuncValueTable MInLocs, MOutLocs; std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2); @@ -3076,7 +3128,7 @@ Output.resize(5); // A dominating assign should propagate to all blocks. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3085,20 +3137,20 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); // Test that an assign in the inner loop causes unresolved PHIs at the heads // of both loops, and no output location. Dominated blocks do get values. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[2].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3107,16 +3159,16 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRax); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRax); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[2].Vars.clear(); // Same test, but with no assignment in block 0. We should still get values // in dominated blocks. - VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[2].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3125,16 +3177,16 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRax); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRax); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[2].Vars.clear(); // Similarly, assignments in the outer loop gives location to dominated // blocks, but no PHI locations are found at the outer loop head. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[3].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[3].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3143,13 +3195,13 @@ EXPECT_EQ(Output[3].size(), 0ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRax); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[3].Vars.clear(); - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[1].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3158,11 +3210,11 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRax); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRax); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRax); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); @@ -3170,8 +3222,8 @@ // With an assignment of the same value in the inner loop, we should work out // that all PHIs can be eliminated and the same value is live-through the // whole function. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[2].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3180,13 +3232,13 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRspID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRsp); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRspID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[2].Vars.clear(); @@ -3201,8 +3253,8 @@ // one. Even though RspPHIInBlk2 isn't available later in the function, we // should still produce a live-in value. The fact it's unavailable is a // different concern. - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[2].Vars.insert({Var, DbgValue(LiveInRaxID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3211,9 +3263,9 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, LiveInRax); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), LiveInRaxID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, LiveInRax); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), LiveInRaxID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[2].Vars.clear(); @@ -3227,8 +3279,8 @@ MOutLocs[2][0] = RspDefInBlk2; MInLocs[3][0] = RspDefInBlk2; MOutLocs[3][0] = RspDefInBlk2; - VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); - VLocs[2].Vars.insert({Var, DbgValue(RspDefInBlk2, EmptyProps, DbgValue::Def)}); + VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); + VLocs[2].Vars.insert({Var, DbgValue(RspDefInBlk2ID, EmptyProps)}); buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, MInLocs, VLocs); EXPECT_EQ(Output[0].size(), 0ul); @@ -3237,13 +3289,13 @@ ASSERT_EQ(Output[3].size(), 1ul); ASSERT_EQ(Output[4].size(), 1ul); EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), RspPHIInBlk1ID); EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk2); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), RspPHIInBlk2ID); EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[3][0].second.ID, RspDefInBlk2); + EXPECT_EQ(Output[3][0].second.getDbgOpID(0), RspDefInBlk2ID); EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); - EXPECT_EQ(Output[4][0].second.ID, RspDefInBlk2); + EXPECT_EQ(Output[4][0].second.getDbgOpID(0), RspDefInBlk2ID); ClearOutputs(); VLocs[0].Vars.clear(); VLocs[2].Vars.clear();