Index: llvm/include/llvm/CodeGen/MachineInstr.h =================================================================== --- llvm/include/llvm/CodeGen/MachineInstr.h +++ llvm/include/llvm/CodeGen/MachineInstr.h @@ -282,6 +282,13 @@ /// defined by this instruction. unsigned DebugInstrNum; +#ifndef NDEBUG + unsigned UID; + static unsigned NextUID; +#endif + + void setUID(); + // Intrusive list support friend struct ilist_traits; friend struct ilist_callback_traits; Index: llvm/include/llvm/IR/Value.h =================================================================== --- llvm/include/llvm/IR/Value.h +++ llvm/include/llvm/IR/Value.h @@ -121,6 +121,14 @@ unsigned HasDescriptor : 1; private: + +#ifndef NDEBUG + unsigned UID; + static unsigned NextUID; +#endif + + void setUID(); + template // UseT == 'Use' or 'const Use' class use_iterator_impl { friend class Value; @@ -225,6 +233,11 @@ Value(const Value &) = delete; Value &operator=(const Value &) = delete; +#ifndef NDEBUG + /// Returns unique ID of Value + unsigned getUID() const { return UID; } +#endif + /// Delete a pointer to a generic Value. void deleteValue(); Index: llvm/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/lib/CodeGen/MachineInstr.cpp +++ llvm/lib/CodeGen/MachineInstr.cpp @@ -60,6 +60,8 @@ using namespace llvm; +extern cl::opt PrintUIDs; + static const MachineFunction *getMFIfAvailable(const MachineInstr &MI) { if (const MachineBasicBlock *MBB = MI.getParent()) if (const MachineFunction *MF = MBB->getParent()) @@ -107,6 +109,8 @@ if (!NoImp) addImplicitDefUseOperands(MF); + + setUID(); } /// MachineInstr ctor - Copies MachineInstr arg exactly. @@ -134,8 +138,19 @@ // Copy all the sensible flags. setFlags(MI.Flags); + + setUID(); +} + +void MachineInstr::setUID() { +#ifndef NDEBUG + UID = NextUID; + ++NextUID; +#endif } +unsigned MachineInstr::NextUID; + void MachineInstr::moveBefore(MachineInstr *MovePos) { MovePos->getParent()->splice(MovePos, getParent(), getIterator()); } @@ -1883,6 +1898,16 @@ } // TODO: DBG_LABEL + if (PrintUIDs) { +#ifndef NDEBUG + if (!HaveSemi) { + OS << ";"; + HaveSemi = true; + } + OS << " UID:" << UID; +#endif + } + if (AddNewLine) OS << '\n'; } Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -88,6 +88,9 @@ using namespace llvm; +cl::opt PrintUIDs("print-uids", cl::Hidden, cl::init(false), + cl::desc("Print instruction IDs in IR dumps")); + // Make virtual table appear in this compilation unit. AssemblyAnnotationWriter::~AssemblyAnnotationWriter() = default; @@ -4007,6 +4010,13 @@ if (AnnotationWriter) AnnotationWriter->printInfoComment(V, Out); + + if (PrintUIDs) { +#ifndef NDEBUG + Out << " ; UID:"; + Out << V.getUID(); +#endif + } } static void maybePrintCallAddrSpace(const Value *Operand, const Instruction *I, Index: llvm/lib/IR/Value.cpp =================================================================== --- llvm/lib/IR/Value.cpp +++ llvm/lib/IR/Value.cpp @@ -68,8 +68,15 @@ (/*SubclassID < ConstantFirstVal ||*/ SubclassID > ConstantLastVal)) assert((VTy->isFirstClassType() || VTy->isVoidTy()) && "Cannot create non-first-class values except for constants!"); - static_assert(sizeof(Value) == 2 * sizeof(void *) + 2 * sizeof(unsigned), +#ifdef NDEBUG + constexpr bool HasUID = false; +#else + constexpr bool HasUID = true; +#endif + static_assert(sizeof(Value) == 2 * sizeof(void *) + 2 * sizeof(unsigned) + + (HasUID ? sizeof(void *) : 0), "Value too big"); + setUID(); } Value::~Value() { @@ -106,6 +113,15 @@ destroyValueName(); } +void Value::setUID() { +#ifndef NDEBUG + UID = NextUID; + ++NextUID; +#endif +} + +unsigned Value::NextUID; + void Value::deleteValue() { switch (getValueID()) { #define HANDLE_VALUE(Name) \