[llvm] [DebugInfo] Make DIExpression inherit from Metadata and it always should be unique (PR #79335)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 24 09:29:02 PST 2024


https://github.com/phyBrackets created https://github.com/llvm/llvm-project/pull/79335

`DIExpression` no longer inherits from `MDNode`. This change was motivated by the need to ensure that `DIExpression` instances have a unique storage type and there was a bit discussion over on [discourse]( https://discourse.llvm.org/t/distinction-of-diexpression-node/71747 ) .

>From b577ea3a85367df9af067619b01ee2a0cca8894d Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Wed, 24 Jan 2024 22:16:02 +0530
Subject: [PATCH] [DebugInfo] Make DIExpression inherit from Metadata and it
 always should be unique

---
 llvm/include/llvm/AsmParser/LLParser.h        |  1 +
 .../CodeGen/GlobalISel/MachineIRBuilder.h     |  8 ++--
 .../llvm/CodeGen/MachineInstrBuilder.h        | 19 ++++++--
 llvm/include/llvm/CodeGen/MachineOperand.h    | 16 ++++++-
 llvm/include/llvm/IR/DebugInfoMetadata.h      | 26 +++++------
 llvm/include/llvm/IR/Metadata.def             |  2 +-
 llvm/lib/AsmParser/LLParser.cpp               | 22 ++++-----
 llvm/lib/Bitcode/Reader/MetadataLoader.cpp    |  3 +-
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp     | 13 ++++--
 .../CodeGen/GlobalISel/MachineIRBuilder.cpp   |  8 ++--
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       | 15 +++---
 llvm/lib/CodeGen/MachineInstr.cpp             |  8 ++--
 .../CodeGen/SelectionDAG/SelectionDAGISel.cpp |  2 +-
 llvm/lib/IR/DIBuilder.cpp                     |  2 -
 llvm/lib/IR/DebugInfoMetadata.cpp             | 19 ++++++--
 llvm/lib/IR/LLVMContextImpl.h                 | 46 +++++++++++++++++++
 llvm/lib/IR/Verifier.cpp                      |  1 +
 .../WebAssembly/WebAssemblyDebugFixup.cpp     |  2 +-
 llvm/lib/Transforms/Utils/ValueMapper.cpp     | 12 ++++-
 llvm/unittests/IR/MetadataTest.cpp            |  3 --
 20 files changed, 152 insertions(+), 76 deletions(-)

diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index cf358c384f52033..af4423cb4a7ca15 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -579,6 +579,7 @@ namespace llvm {
     bool parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
                               PerFunctionState *PFS);
     bool parseDIArgList(Metadata *&MD, PerFunctionState *PFS);
+    bool parseDIExpression(Metadata *&MD);
     bool parseMetadata(Metadata *&MD, PerFunctionState *PFS);
     bool parseMDTuple(MDNode *&MD, bool IsDistinct = false);
     bool parseMDNode(MDNode *&N);
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 1387a0a37561c4b..2691188d9cffc17 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -410,26 +410,26 @@ class MachineIRBuilder {
   /// Build and insert a DBG_VALUE instruction expressing the fact that the
   /// associated \p Variable lives in \p Reg (suitably modified by \p Expr).
   MachineInstrBuilder buildDirectDbgValue(Register Reg, const MDNode *Variable,
-                                          const MDNode *Expr);
+                                          const Metadata *Expr);
 
   /// Build and insert a DBG_VALUE instruction expressing the fact that the
   /// associated \p Variable lives in memory at \p Reg (suitably modified by \p
   /// Expr).
   MachineInstrBuilder buildIndirectDbgValue(Register Reg,
                                             const MDNode *Variable,
-                                            const MDNode *Expr);
+                                            const Metadata *Expr);
 
   /// Build and insert a DBG_VALUE instruction expressing the fact that the
   /// associated \p Variable lives in the stack slot specified by \p FI
   /// (suitably modified by \p Expr).
   MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable,
-                                      const MDNode *Expr);
+                                      const Metadata *Expr);
 
   /// Build and insert a DBG_VALUE instructions specifying that \p Variable is
   /// given by \p C (suitably modified by \p Expr).
   MachineInstrBuilder buildConstDbgValue(const Constant &C,
                                          const MDNode *Variable,
-                                         const MDNode *Expr);
+                                         const Metadata *Expr);
 
   /// Build and insert a DBG_LABEL instructions specifying that \p Label is
   /// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label".
diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index 954d8e6770a294f..c0c2a4ea4c0c23a 100644
--- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -245,6 +245,17 @@ class MachineInstrBuilder {
     return *this;
   }
 
+  const MachineInstrBuilder &addMetadata(const Metadata *MD) const {
+    MI->addOperand(*MF, MachineOperand::CreateMetadata(MD));
+    assert((MI->isDebugValueLike() ? static_cast<bool>(MI->getDebugVariable())
+                                   : true) &&
+           "first MDNode argument of a DBG_VALUE not a variable");
+    assert((MI->isDebugLabel() ? static_cast<bool>(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;
@@ -488,14 +499,14 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
 MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
                             const MCInstrDesc &MCID, bool IsIndirect,
                             Register Reg, const MDNode *Variable,
-                            const MDNode *Expr);
+                            const Metadata *Expr);
 
 /// This version of the builder builds a DBG_VALUE or DBG_VALUE_LIST intrinsic
 /// for a MachineOperand.
 MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
                             const MCInstrDesc &MCID, bool IsIndirect,
                             ArrayRef<MachineOperand> MOs,
-                            const MDNode *Variable, const MDNode *Expr);
+                            const MDNode *Variable, const Metadata *Expr);
 
 /// This version of the builder builds a DBG_VALUE intrinsic
 /// for either a value in a register or a register-indirect
@@ -504,7 +515,7 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
                             MachineBasicBlock::iterator I, const DebugLoc &DL,
                             const MCInstrDesc &MCID, bool IsIndirect,
                             Register Reg, const MDNode *Variable,
-                            const MDNode *Expr);
+                            const Metadata *Expr);
 
 /// This version of the builder builds a DBG_VALUE, DBG_INSTR_REF, or
 /// DBG_VALUE_LIST intrinsic for a machine operand and inserts it at position I.
@@ -512,7 +523,7 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
                             MachineBasicBlock::iterator I, const DebugLoc &DL,
                             const MCInstrDesc &MCID, bool IsIndirect,
                             ArrayRef<MachineOperand> MOs,
-                            const MDNode *Variable, const MDNode *Expr);
+                            const MDNode *Variable, const Metadata *Expr);
 
 /// Clone a DBG_VALUE whose value has been spilled to FrameIndex.
 MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h
index 63a172134538c42..9d5532c7d812ec1 100644
--- a/llvm/include/llvm/CodeGen/MachineOperand.h
+++ b/llvm/include/llvm/CodeGen/MachineOperand.h
@@ -31,6 +31,7 @@ class MachineInstr;
 class MachineRegisterInfo;
 class MCCFIInstruction;
 class MDNode;
+class Metadata;
 class ModuleSlotTracker;
 class TargetIntrinsicInfo;
 class TargetRegisterInfo;
@@ -173,6 +174,7 @@ class MachineOperand {
     int64_t ImmVal;          // For MO_Immediate.
     const uint32_t *RegMask; // For MO_RegisterMask and MO_RegisterLiveOut.
     const MDNode *MD;        // For MO_Metadata.
+    const Metadata* Expr;
     MCSymbol *Sym;           // For MO_MCSymbol.
     unsigned CFIIndex;       // For MO_CFI.
     Intrinsic::ID IntrinsicID; // For MO_IntrinsicID.
@@ -677,6 +679,11 @@ class MachineOperand {
     return Contents.MD;
   }
 
+  const Metadata *getMetadataDI() const {
+    assert(isMetadata() && "Wrong MachineOperand accessor");
+    return Contents.Expr;
+  }
+
   //===--------------------------------------------------------------------===//
   // Mutators for various operand types.
   //===--------------------------------------------------------------------===//
@@ -710,9 +717,9 @@ class MachineOperand {
     Contents.OffsetedInfo.Val.Index = Idx;
   }
 
-  void setMetadata(const MDNode *MD) {
+  void setMetadata(const Metadata *MD) {
     assert(isMetadata() && "Wrong MachineOperand mutator");
-    Contents.MD = MD;
+    Contents.Expr = MD;
   }
 
   void setInstrRefInstrIndex(unsigned InstrIdx) {
@@ -946,6 +953,11 @@ class MachineOperand {
     Op.Contents.MD = Meta;
     return Op;
   }
+  static MachineOperand CreateMetadata(const Metadata *Meta) {
+    MachineOperand Op(MachineOperand::MO_Metadata);
+    Op.Contents.Expr = Meta;
+    return Op;
+  }
 
   static MachineOperand CreateMCSymbol(MCSymbol *Sym,
                                        unsigned TargetFlags = 0) {
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 156f6eb49253de7..207deed8a78dd97 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2656,31 +2656,27 @@ class DIVariable : public DINode {
 /// DW_OP_stack_value) is the constant variable value.
 ///
 /// TODO: Co-allocate the expression elements.
-/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
-/// storage types.
-class DIExpression : public MDNode {
+class DIExpression : public Metadata, ReplaceableMetadataImpl {
+  friend class ReplaceableMetadataImpl;
   friend class LLVMContextImpl;
-  friend class MDNode;
 
   std::vector<uint64_t> Elements;
 
-  DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements)
-      : MDNode(C, DIExpressionKind, Storage, std::nullopt),
+  DIExpression(LLVMContext &C, ArrayRef<uint64_t> Elements)
+      : Metadata(DIExpressionKind, Uniqued), ReplaceableMetadataImpl(C),
         Elements(Elements.begin(), Elements.end()) {}
   ~DIExpression() = default;
 
   static DIExpression *getImpl(LLVMContext &Context,
-                               ArrayRef<uint64_t> Elements, StorageType Storage,
-                               bool ShouldCreate = true);
-
-  TempDIExpression cloneImpl() const {
-    return getTemporary(getContext(), getElements());
-  }
+                               ArrayRef<uint64_t> Elements);
 
 public:
-  DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements))
-
-  TempDIExpression clone() const { return cloneImpl(); }
+    LLVMContext &getContext() const {
+        return ReplaceableMetadataImpl::getContext();
+    }
+    static inline DIExpression *get(LLVMContext &Context, ArrayRef<uint64_t> Elements) {
+        return getImpl(Context, Elements);
+    }
 
   ArrayRef<uint64_t> getElements() const { return Elements; }
 
diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index a3cfb9ad6e3e785..0edbe931c75ed8e 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -81,7 +81,7 @@ HANDLE_METADATA_LEAF(DIArgList)
 HANDLE_MDNODE_BRANCH(MDNode)
 HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation)
-HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression)
+HANDLE_METADATA_LEAF(DIExpression)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariableExpression)
 HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode)
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index d6c5993797de111..e7b06f8c5fef702 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -892,16 +892,7 @@ bool LLParser::parseNamedMetadata() {
   if (Lex.getKind() != lltok::rbrace)
     do {
       MDNode *N = nullptr;
-      // parse DIExpressions inline as a special case. They are still MDNodes,
-      // so they can still appear in named metadata. Remove this logic if they
-      // become plain Metadata.
-      if (Lex.getKind() == lltok::MetadataVar &&
-          Lex.getStrVal() == "DIExpression") {
-        if (parseDIExpression(N, /*IsDistinct=*/false))
-          return true;
-        // DIArgLists should only appear inline in a function, as they may
-        // contain LocalAsMetadata arguments which require a function context.
-      } else if (Lex.getKind() == lltok::MetadataVar &&
+       if (Lex.getKind() == lltok::MetadataVar &&
                  Lex.getStrVal() == "DIArgList") {
         return tokError("found DIArgList outside of function");
       } else if (parseToken(lltok::exclaim, "Expected '!' here") ||
@@ -5569,7 +5560,7 @@ bool LLParser::parseDILabel(MDNode *&Result, bool IsDistinct) {
 
 /// parseDIExpression:
 ///   ::= !DIExpression(0, 7, -1)
-bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) {
+bool LLParser::parseDIExpression(Metadata *&Result) {
   assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
   Lex.Lex();
 
@@ -5611,7 +5602,7 @@ bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) {
   if (parseToken(lltok::rparen, "expected ')' here"))
     return true;
 
-  Result = GET_OR_DISTINCT(DIExpression, (Context, Elements));
+  Result = DIExpression::get(Context, Elements);
   return false;
 }
 
@@ -5760,6 +5751,13 @@ bool LLParser::parseMetadata(Metadata *&MD, PerFunctionState *PFS) {
       MD = AL;
       return false;
     }
+    else if (Lex.getStrVal() == "DIExpression") {
+      Metadata *Expr;
+      if (parseDIExpression(Expr))
+        return true;
+      MD = Expr;
+      return false;
+    }
     MDNode *N;
     if (parseSpecializedMDNode(N)) {
       return true;
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 770eb83af17f9b0..6ee44110d47a145 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -2145,7 +2145,6 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     if (Record.size() < 1)
       return error("Invalid record");
 
-    IsDistinct = Record[0] & 1;
     uint64_t Version = Record[0] >> 1;
     auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
 
@@ -2153,7 +2152,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     if (Error Err = upgradeDIExpression(Version, Elts, Buffer))
       return Err;
 
-    MetadataList.assignValue(GET_OR_DISTINCT(DIExpression, (Context, Elts)),
+    MetadataList.assignValue(DIExpression::get(Context, Elts),
                              NextMetadataNo);
     NextMetadataNo++;
     break;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index a5fc267b1883bfe..d2f05597deb5a58 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -355,7 +355,7 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
   void writeDILabel(const DILabel *N,
                     SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
   void writeDIExpression(const DIExpression *N,
-                         SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
+                         SmallVectorImpl<uint64_t> &Record);
   void writeDIGlobalVariableExpression(const DIGlobalVariableExpression *N,
                                        SmallVectorImpl<uint64_t> &Record,
                                        unsigned Abbrev);
@@ -2138,14 +2138,13 @@ void ModuleBitcodeWriter::writeDILabel(
 }
 
 void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
-                                            SmallVectorImpl<uint64_t> &Record,
-                                            unsigned Abbrev) {
+                                            SmallVectorImpl<uint64_t> &Record) {
   Record.reserve(N->getElements().size() + 1);
   const uint64_t Version = 3 << 1;
-  Record.push_back((uint64_t)N->isDistinct() | Version);
+  Record.push_back(Version);
   Record.append(N->elements_begin(), N->elements_end());
 
-  Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev);
+  Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record);
   Record.clear();
 }
 
@@ -2305,6 +2304,10 @@ void ModuleBitcodeWriter::writeMetadataRecords(
       writeDIArgList(AL, Record);
       continue;
     }
+    if (auto *AL = dyn_cast<DIExpression>(MD)) {
+      writeDIExpression(AL, Record);
+      continue;
+    }
     writeValueAsMetadata(cast<ValueAsMetadata>(MD), Record);
   }
 }
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index a5827c26c04f48b..21aebf0166e5684 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -48,7 +48,7 @@ MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
 
 MachineInstrBuilder
 MachineIRBuilder::buildDirectDbgValue(Register Reg, const MDNode *Variable,
-                                      const MDNode *Expr) {
+                                      const Metadata *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
   assert(
@@ -61,7 +61,7 @@ MachineIRBuilder::buildDirectDbgValue(Register Reg, const MDNode *Variable,
 
 MachineInstrBuilder
 MachineIRBuilder::buildIndirectDbgValue(Register Reg, const MDNode *Variable,
-                                        const MDNode *Expr) {
+                                        const Metadata *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
   assert(
@@ -74,7 +74,7 @@ MachineIRBuilder::buildIndirectDbgValue(Register Reg, const MDNode *Variable,
 
 MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
                                                       const MDNode *Variable,
-                                                      const MDNode *Expr) {
+                                                      const Metadata *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
   assert(
@@ -89,7 +89,7 @@ MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
 
 MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
                                                          const MDNode *Variable,
-                                                         const MDNode *Expr) {
+                                                         const Metadata *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
   assert(
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index ede4291fe26dc95..d545e21c3d12ace 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -472,7 +472,7 @@ class MIParser {
   bool parseExternalSymbolOperand(MachineOperand &Dest);
   bool parseMCSymbolOperand(MachineOperand &Dest);
   [[nodiscard]] bool parseMDNode(MDNode *&Node);
-  bool parseDIExpression(MDNode *&Expr);
+  bool parseDIExpression(Metadata *&Expr);
   bool parseDILocation(MDNode *&Expr);
   bool parseMetadataOperand(MachineOperand &Dest);
   bool parseCFIOffset(int &Offset);
@@ -1269,9 +1269,6 @@ bool MIParser::parseStandaloneMDNode(MDNode *&Node) {
   if (Token.is(MIToken::exclaim)) {
     if (parseMDNode(Node))
       return true;
-  } else if (Token.is(MIToken::md_diexpr)) {
-    if (parseDIExpression(Node))
-      return true;
   } else if (Token.is(MIToken::md_dilocation)) {
     if (parseDILocation(Node))
       return true;
@@ -2292,7 +2289,7 @@ bool MIParser::parseMDNode(MDNode *&Node) {
   return false;
 }
 
-bool MIParser::parseDIExpression(MDNode *&Expr) {
+bool MIParser::parseDIExpression(Metadata *&Expr) {
   assert(Token.is(MIToken::md_diexpr));
   lex();
 
@@ -2442,15 +2439,15 @@ bool MIParser::parseDILocation(MDNode *&Loc) {
 }
 
 bool MIParser::parseMetadataOperand(MachineOperand &Dest) {
-  MDNode *Node = nullptr;
+    Metadata *Meta = nullptr;
   if (Token.is(MIToken::exclaim)) {
-    if (parseMDNode(Node))
+     if (parseMDNode(reinterpret_cast<MDNode *&>(Meta)))
       return true;
   } else if (Token.is(MIToken::md_diexpr)) {
-    if (parseDIExpression(Node))
+    if (parseDIExpression(Meta))
       return true;
   }
-  Dest = MachineOperand::CreateMetadata(Node);
+  Dest = MachineOperand::CreateMetadata(reinterpret_cast<MDNode *>(Meta));
   return false;
 }
 
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 27eae372f8ad764..740edf06eb2b205 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2153,7 +2153,7 @@ void MachineInstr::emitError(StringRef Msg) const {
 MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
                                   const MCInstrDesc &MCID, bool IsIndirect,
                                   Register Reg, const MDNode *Variable,
-                                  const MDNode *Expr) {
+                                  const Metadata *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
   assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
@@ -2169,7 +2169,7 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
 MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
                                   const MCInstrDesc &MCID, bool IsIndirect,
                                   ArrayRef<MachineOperand> DebugOps,
-                                  const MDNode *Variable, const MDNode *Expr) {
+                                  const MDNode *Variable, const Metadata *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
   assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
@@ -2204,7 +2204,7 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
                                   MachineBasicBlock::iterator I,
                                   const DebugLoc &DL, const MCInstrDesc &MCID,
                                   bool IsIndirect, Register Reg,
-                                  const MDNode *Variable, const MDNode *Expr) {
+                                  const MDNode *Variable, const Metadata *Expr) {
   MachineFunction &MF = *BB.getParent();
   MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Variable, Expr);
   BB.insert(I, MI);
@@ -2216,7 +2216,7 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
                                   const DebugLoc &DL, const MCInstrDesc &MCID,
                                   bool IsIndirect,
                                   ArrayRef<MachineOperand> DebugOps,
-                                  const MDNode *Variable, const MDNode *Expr) {
+                                  const MDNode *Variable, const Metadata *Expr) {
   MachineFunction &MF = *BB.getParent();
   MachineInstr *MI =
       BuildMI(MF, DL, MCID, IsIndirect, DebugOps, Variable, Expr);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 359d738d2ca09fd..6de40d703a9286b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -614,7 +614,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
       MachineInstr *Def = RegInfo->getVRegDef(LDI->second);
       MachineBasicBlock::iterator InsertPos = Def;
       const MDNode *Variable = MI->getDebugVariable();
-      const MDNode *Expr = MI->getDebugExpression();
+      const DIExpression *Expr = MI->getDebugExpression();
       DebugLoc DL = MI->getDebugLoc();
       bool IsIndirect = MI->isIndirectDebugValue();
       if (IsIndirect)
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 62efaba025344b5..392d33242cb25f7 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -1045,7 +1045,6 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
     DeclareFn = getDeclareIntrin(M);
 
   trackIfUnresolved(VarInfo);
-  trackIfUnresolved(Expr);
   Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage),
                    MetadataAsValue::get(VMContext, VarInfo),
                    MetadataAsValue::get(VMContext, Expr)};
@@ -1071,7 +1070,6 @@ Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn,
          "Expected matching subprograms");
 
   trackIfUnresolved(VarInfo);
-  trackIfUnresolved(Expr);
   Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V),
                    MetadataAsValue::get(VMContext, VarInfo),
                    MetadataAsValue::get(VMContext, Expr)};
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 51950fc937f0aba..d2a039876fe2412 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1351,12 +1351,21 @@ DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
   Metadata *Ops[] = {Scope, Name, File};
   DEFINE_GETIMPL_STORE(DILabel, (Line), Ops);
 }
+DIExpression *DIExpression::getImpl(LLVMContext &Context, ArrayRef<uint64_t> Elements) {
+  auto &DIExpressions = Context.pImpl->DIExpressions;
+  DIExpressionKeyInfo Key(Elements);
 
-DIExpression *DIExpression::getImpl(LLVMContext &Context,
-                                    ArrayRef<uint64_t> Elements,
-                                    StorageType Storage, bool ShouldCreate) {
-  DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements));
-  DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements));
+  // Check if an existing expression matches the key
+  auto It = DIExpressions.find_as(Key);
+  if (It != DIExpressions.end())
+    return *It;
+
+  // Create a new DIExpression if not found
+  DIExpression *NewExpr = new DIExpression(Context, Elements);
+
+  // Insert the new expression into the set
+  DIExpressions.insert(NewExpr);
+  return NewExpr;
 }
 bool DIExpression::isEntryValue() const {
   if (auto singleLocElts = getSingleLocationExpressionElements()) {
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 6a20291344989dd..37f1471bb5005fb 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1350,6 +1350,51 @@ struct DIArgListInfo {
   }
 };
 
+struct DIExpressionKeyInfo {
+  ArrayRef<uint64_t> Elements;
+
+  DIExpressionKeyInfo(ArrayRef<uint64_t> Elements) : Elements(Elements) {}
+  DIExpressionKeyInfo(const DIExpression *Expr) : Elements(Expr->getElements()) {}
+
+  bool isKeyOf(const DIExpression *RHS) const {
+    return Elements == RHS->getElements();
+  }
+
+  unsigned getHashValue() const {
+    return hash_combine_range(Elements.begin(), Elements.end());
+  }
+};
+
+struct DIExpressionInfo {
+  using KeyTy = DIExpressionKeyInfo;
+
+  static inline DIExpression *getEmptyKey() {
+    return DenseMapInfo<DIExpression *>::getEmptyKey();
+  }
+
+  static inline DIExpression *getTombstoneKey() {
+    return DenseMapInfo<DIExpression *>::getTombstoneKey();
+  }
+
+  static unsigned getHashValue(const KeyTy &Key) {
+    return Key.getHashValue();
+  }
+
+  static unsigned getHashValue(const DIExpression *Expr) {
+    return KeyTy(Expr).getHashValue();
+  }
+
+  static bool isEqual(const KeyTy &LHS, const DIExpression *RHS) {
+    if (RHS == getEmptyKey() || RHS == getTombstoneKey())
+      return false;
+    return LHS.isKeyOf(RHS);
+  }
+
+  static bool isEqual(const DIExpression *LHS, const DIExpression *RHS) {
+    return LHS == RHS;
+  }
+};
+
 /// DenseMapInfo for MDNode subclasses.
 template <class NodeTy> struct MDNodeInfo {
   using KeyTy = MDNodeKeyImpl<NodeTy>;
@@ -1499,6 +1544,7 @@ class LLVMContextImpl {
   DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;
   DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
   DenseSet<DIArgList *, DIArgListInfo> DIArgLists;
+  DenseSet<DIExpression *, DIExpressionInfo> DIExpressions;
 
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
   DenseSet<CLASS *, CLASS##Info> CLASS##s;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 91cf91fbc788bd9..a11d5400f78b1fe 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -488,6 +488,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
   void visitMetadataAsValue(const MetadataAsValue &MD, Function *F);
   void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F);
   void visitDIArgList(const DIArgList &AL, Function *F);
+  void visitDIExpression(const DIExpression &DI);
   void visitComdat(const Comdat &C);
   void visitModuleIdents();
   void visitModuleCommandLines();
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp
index 4a75bab6b95ddcd..6fc6b0ebd9b03bf 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp
@@ -140,7 +140,7 @@ bool WebAssemblyDebugFixup::runOnMachineFunction(MachineFunction &MF) {
                       Prev.DebugValue->getDebugLoc(),
                       TII->get(WebAssembly::DBG_VALUE), false, Register(),
                       Prev.DebugValue->getOperand(2).getMetadata(),
-                      Prev.DebugValue->getOperand(3).getMetadata());
+                      Prev.DebugValue->getOperand(3).getMetadataDI());
             }
           }
         }
diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp
index 380541ffdd49d6e..eddc37d133e46cc 100644
--- a/llvm/lib/Transforms/Utils/ValueMapper.cpp
+++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp
@@ -615,7 +615,7 @@ std::optional<Metadata *> MDNodeMapper::tryToMapOperand(const Metadata *Op) {
               M.getVM().getMappedMD(Op)) &&
              "Expected Value to be memoized");
     else
-      assert((isa<MDString>(Op) || M.getVM().getMappedMD(Op)) &&
+      assert((isa<DIExpression>(Op) || isa<MDString>(Op) || M.getVM().getMappedMD(Op)) &&
              "Expected result to be memoized");
 #endif
     return *MappedOp;
@@ -807,7 +807,12 @@ void MDNodeMapper::mapNodesInPOT(UniquedGraph &G) {
         return *MappedOp;
       (void)D;
       assert(G.Info[Old].ID > D.ID && "Expected a forward reference");
-      return &G.getFwdReference(*cast<MDNode>(Old));
+      if (auto *MDN = dyn_cast<MDNode>(Old)) {
+        // Handle MDNode
+        return &G.getFwdReference(*MDN);
+      } else if (isa<DIExpression>(Old)) {
+            return Old;
+          }
     });
 
     auto *NewN = MDNode::replaceWithUniqued(std::move(ClonedN));
@@ -878,6 +883,9 @@ std::optional<Metadata *> Mapper::mapSimpleMetadata(const Metadata *MD) {
 
   if (isa<MDString>(MD))
     return const_cast<Metadata *>(MD);
+  
+  if(isa<DIExpression>(MD))
+    return const_cast<Metadata *>(MD);
 
   // This is a module-level metadata.  If nothing at the module level is
   // changing, use an identity mapping.
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 767dd1a59d2b9e9..27ba21cb7d512be 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -3094,9 +3094,6 @@ TEST_F(DIExpressionTest, get) {
   EXPECT_EQ(78u, N->getElement(3));
   EXPECT_EQ(0u, N->getElement(4));
 
-  TempDIExpression Temp = N->clone();
-  EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
-
   // Test DIExpression::prepend().
   uint64_t Elts0[] = {dwarf::DW_OP_LLVM_fragment, 0, 32};
   auto *N0 = DIExpression::get(Context, Elts0);



More information about the llvm-commits mailing list