[llvm] ee76525 - [DebugInfo] Enforce implicit constraints on `distinct` MDNodes

Scott Linder via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 9 10:19:21 PST 2021


Author: Scott Linder
Date: 2021-11-09T18:19:11Z
New Revision: ee7652569854af567ba83e5255d70e80cc8619a1

URL: https://github.com/llvm/llvm-project/commit/ee7652569854af567ba83e5255d70e80cc8619a1
DIFF: https://github.com/llvm/llvm-project/commit/ee7652569854af567ba83e5255d70e80cc8619a1.diff

LOG: [DebugInfo] Enforce implicit constraints on `distinct` MDNodes

Add UNIQUED and DISTINCT properties in Metadata.def and use them to
implement restrictions on the `distinct` property of MDNodes:

* DIExpression can currently be parsed from IR or read from bitcode
  as `distinct`, but this property is silently dropped when printing
  to IR. This causes accepted IR to fail to round-trip. As DIExpression
  appears inline at each use in the canonical form of IR, it cannot
  actually be `distinct` anyway, as there is no syntax to describe it.
* Similarly, DIArgList is conceptually always uniqued. It is currently
  restricted to only appearing in contexts where there is no syntax for
  `distinct`, but for consistency it is treated equivalently to
  DIExpression in this patch.
* DICompileUnit is already restricted to always being `distinct`, but
  along with adding general support for the inverse restriction I went
  ahead and described this in Metadata.def and updated the parser to be
  general. Future nodes which have this restriction can share this
  support.

The new UNIQUED property applies to DIExpression and DIArgList, and
forbids them to be `distinct`. It also implies they are canonically
printed inline at each use, rather than via MDNode ID.

The new DISTINCT property applies to DICompileUnit, and requires it to
be `distinct`.

A potential alternative change is to forbid the non-inline syntax for
DIExpression entirely, as is done with DIArgList implicitly by requiring
it appear in the context of a function. For example, we would forbid:

    !named = !{!0}
    !0 = !DIExpression()

Instead we would only accept the equivalent inlined version:

    !named = !{!DIExpression()}

This essentially removes the ability to create a `distinct` DIExpression
by construction, as there is no syntax for `distinct` inline. If this
patch is accepted as-is, the result would be that the non-canonical
version is accepted, but the following would be an error and produce a diagnostic:

    !named = !{!0}
    ; error: 'distinct' not allowed for !DIExpression()
    !0 = distinct !DIExpression()

Also update some documentation to consistently use the inline syntax for
DIExpression, and to describe the restrictions on `distinct` for nodes
where applicable.

Reviewed By: StephenTozer, t-tye

Differential Revision: https://reviews.llvm.org/D104827

Added: 
    llvm/test/Assembler/invalid-diarglist-outside-function.ll
    llvm/test/Assembler/invalid-diexpression-distinct.ll
    llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll
    llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc

Modified: 
    llvm/docs/LangRef.rst
    llvm/docs/SourceLevelDebugging.rst
    llvm/include/llvm/AsmParser/LLParser.h
    llvm/include/llvm/IR/DebugInfoMetadata.h
    llvm/include/llvm/IR/Metadata.def
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Reader/MetadataLoader.cpp
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/CodeGen/MIRParser/MIParser.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/DebugInfoMetadata.cpp
    llvm/lib/IR/LLVMContextImpl.cpp
    llvm/lib/IR/LLVMContextImpl.h
    llvm/lib/IR/Metadata.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 3a5bc9c199d55..92dfd6c392dde 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -5200,21 +5200,22 @@ metadata nodes are related to debug info.
 DICompileUnit
 """""""""""""
 
-``DICompileUnit`` nodes represent a compile unit. The ``enums:``,
-``retainedTypes:``, ``globals:``, ``imports:`` and ``macros:`` fields are tuples
-containing the debug info to be emitted along with the compile unit, regardless
-of code optimizations (some nodes are only emitted if there are references to
-them from instructions). The ``debugInfoForProfiling:`` field is a boolean
-indicating whether or not line-table discriminators are updated to provide
-more-accurate debug info for profiling results.
+``DICompileUnit`` nodes represent a compile unit. ``DICompileUnit`` nodes must
+be ``distinct``. The ``enums:``, ``retainedTypes:``, ``globals:``, ``imports:``
+and ``macros:`` fields are tuples containing the debug info to be emitted along
+with the compile unit, regardless of code optimizations (some nodes are only
+emitted if there are references to them from instructions). The
+``debugInfoForProfiling:`` field is a boolean indicating whether or not
+line-table discriminators are updated to provide more-accurate debug info for
+profiling results.
 
 .. code-block:: text
 
-    !0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
-                        isOptimized: true, flags: "-O2", runtimeVersion: 2,
-                        splitDebugFilename: "abc.debug", emissionKind: FullDebug,
-                        enums: !2, retainedTypes: !3, globals: !4, imports: !5,
-                        macros: !6, dwoId: 0x0abcd)
+    !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
+                                 isOptimized: true, flags: "-O2", runtimeVersion: 2,
+                                 splitDebugFilename: "abc.debug", emissionKind: FullDebug,
+                                 enums: !2, retainedTypes: !3, globals: !4, imports: !5,
+                                 macros: !6, dwoId: 0x0abcd)
 
 Compile unit descriptors provide the root scope for objects declared in a
 specific compilation unit. File descriptors are defined using this scope.  These
@@ -5625,12 +5626,14 @@ DIExpression
 """"""""""""
 
 ``DIExpression`` nodes represent expressions that are inspired by the DWARF
-expression language. They are used in :ref:`debug intrinsics<dbg_intrinsics>`
-(such as ``llvm.dbg.declare`` and ``llvm.dbg.value``) to describe how the
-referenced LLVM variable relates to the source language variable. Debug
-intrinsics are interpreted left-to-right: start by pushing the value/address
-operand of the intrinsic onto a stack, then repeatedly push and evaluate
-opcodes from the DIExpression until the final variable description is produced.
+expression language. ``DIExpression`` nodes must not be ``distinct``, and are
+canonically printed inline at each use. They are used in :ref:`debug
+intrinsics<dbg_intrinsics>` (such as ``llvm.dbg.declare`` and
+``llvm.dbg.value``) to describe how the referenced LLVM variable relates to the
+source language variable. Debug intrinsics are interpreted left-to-right: start
+by pushing the value/address operand of the intrinsic onto a stack, then
+repeatedly push and evaluate opcodes from the DIExpression until the final
+variable description is produced.
 
 The current supported opcode vocabulary is limited:
 
@@ -5708,23 +5711,23 @@ The current supported opcode vocabulary is limited:
 
     IR for "*ptr = 4;"
     --------------
-    call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !20)
+    call void @llvm.dbg.value(metadata i32 4, metadata !17,
+                              metadata !DIExpression(DW_OP_LLVM_implicit_pointer)))
     !17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
                            type: !18)
     !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
     !19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-    !20 = !DIExpression(DW_OP_LLVM_implicit_pointer))
 
     IR for "**ptr = 4;"
     --------------
-    call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !21)
+    call void @llvm.dbg.value(metadata i32 4, metadata !17,
+                              metadata !DIExpression(DW_OP_LLVM_implicit_pointer,
+                                                     DW_OP_LLVM_implicit_pointer)))
     !17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
                            type: !18)
     !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
     !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
     !20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-    !21 = !DIExpression(DW_OP_LLVM_implicit_pointer,
-                        DW_OP_LLVM_implicit_pointer))
 
 DWARF specifies three kinds of simple location descriptions: Register, memory,
 and implicit location descriptions.  Note that a location description is
@@ -5765,12 +5768,13 @@ valid debug intrinsic.
 DIArgList
 """"""""""""
 
-``DIArgList`` nodes hold a list of constant or SSA value references. These are
-used in :ref:`debug intrinsics<dbg_intrinsics>` (currently only in
+``DIArgList`` nodes hold a list of constant or SSA value references.
+``DIArgList`` must not be ``distinct``, must only be used as an argument to a
+function call, and must appear inline at each use. ``DIArgList`` may refer to
+function-local values of the containing function. ``DIArgList`` nodes are used
+in :ref:`debug intrinsics<dbg_intrinsics>` (currently only in
 ``llvm.dbg.value``) in combination with a ``DIExpression`` that uses the
-``DW_OP_LLVM_arg`` operator. Because a DIArgList may refer to local values
-within a function, it must only be used as a function argument, must always be
-inlined, and cannot appear in named metadata.
+``DW_OP_LLVM_arg`` operator.
 
 .. code-block:: text
 

diff  --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst
index dbadaed10eef9..5732e9eb47b6a 100644
--- a/llvm/docs/SourceLevelDebugging.rst
+++ b/llvm/docs/SourceLevelDebugging.rst
@@ -291,17 +291,17 @@ Compiled to LLVM, this function would be represented like this:
     %X = alloca i32, align 4
     %Y = alloca i32, align 4
     %Z = alloca i32, align 4
-    call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !13), !dbg !14
-    store i32 21, i32* %X, align 4, !dbg !14
-    call void @llvm.dbg.declare(metadata i32* %Y, metadata !15, metadata !13), !dbg !16
-    store i32 22, i32* %Y, align 4, !dbg !16
-    call void @llvm.dbg.declare(metadata i32* %Z, metadata !17, metadata !13), !dbg !19
-    store i32 23, i32* %Z, align 4, !dbg !19
-    %0 = load i32, i32* %X, align 4, !dbg !20
-    store i32 %0, i32* %Z, align 4, !dbg !21
-    %1 = load i32, i32* %Y, align 4, !dbg !22
-    store i32 %1, i32* %X, align 4, !dbg !23
-    ret void, !dbg !24
+    call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !DIExpression()), !dbg !13
+    store i32 21, i32* %X, align 4, !dbg !13
+    call void @llvm.dbg.declare(metadata i32* %Y, metadata !14, metadata !DIExpression()), !dbg !15
+    store i32 22, i32* %Y, align 4, !dbg !15
+    call void @llvm.dbg.declare(metadata i32* %Z, metadata !16, metadata !DIExpression()), !dbg !18
+    store i32 23, i32* %Z, align 4, !dbg !18
+    %0 = load i32, i32* %X, align 4, !dbg !19
+    store i32 %0, i32* %Z, align 4, !dbg !20
+    %1 = load i32, i32* %Y, align 4, !dbg !21
+    store i32 %1, i32* %X, align 4, !dbg !22
+    ret void, !dbg !23
   }
 
   ; Function Attrs: nounwind readnone
@@ -327,18 +327,17 @@ Compiled to LLVM, this function would be represented like this:
   !10 = !{!"clang version 3.7.0 (trunk 231150) (llvm/trunk 231154)"}
   !11 = !DILocalVariable(name: "X", scope: !4, file: !1, line: 2, type: !12)
   !12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
-  !13 = !DIExpression()
-  !14 = !DILocation(line: 2, column: 9, scope: !4)
-  !15 = !DILocalVariable(name: "Y", scope: !4, file: !1, line: 3, type: !12)
-  !16 = !DILocation(line: 3, column: 9, scope: !4)
-  !17 = !DILocalVariable(name: "Z", scope: !18, file: !1, line: 5, type: !12)
-  !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5)
-  !19 = !DILocation(line: 5, column: 11, scope: !18)
-  !20 = !DILocation(line: 6, column: 11, scope: !18)
-  !21 = !DILocation(line: 6, column: 9, scope: !18)
-  !22 = !DILocation(line: 8, column: 9, scope: !4)
-  !23 = !DILocation(line: 8, column: 7, scope: !4)
-  !24 = !DILocation(line: 9, column: 3, scope: !4)
+  !13 = !DILocation(line: 2, column: 9, scope: !4)
+  !14 = !DILocalVariable(name: "Y", scope: !4, file: !1, line: 3, type: !12)
+  !15 = !DILocation(line: 3, column: 9, scope: !4)
+  !16 = !DILocalVariable(name: "Z", scope: !17, file: !1, line: 5, type: !12)
+  !17 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5)
+  !18 = !DILocation(line: 5, column: 11, scope: !17)
+  !19 = !DILocation(line: 6, column: 11, scope: !17)
+  !20 = !DILocation(line: 6, column: 9, scope: !17)
+  !21 = !DILocation(line: 8, column: 9, scope: !4)
+  !22 = !DILocation(line: 8, column: 7, scope: !4)
+  !23 = !DILocation(line: 9, column: 3, scope: !4)
 
 
 This example illustrates a few important details about LLVM debugging
@@ -349,21 +348,21 @@ variable definitions, and the code used to implement the function.
 
 .. code-block:: llvm
 
-  call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !13), !dbg !14
+  call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !DIExpression()), !dbg !13
     ; [debug line = 2:7] [debug variable = X]
 
 The first intrinsic ``%llvm.dbg.declare`` encodes debugging information for the
-variable ``X``.  The metadata ``!dbg !14`` attached to the intrinsic provides
+variable ``X``.  The metadata ``!dbg !13`` attached to the intrinsic provides
 scope information for the variable ``X``.
 
 .. code-block:: text
 
-  !14 = !DILocation(line: 2, column: 9, scope: !4)
+  !13 = !DILocation(line: 2, column: 9, scope: !4)
   !4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5,
                               isLocal: false, isDefinition: true, scopeLine: 1,
                               isOptimized: false, retainedNodes: !2)
 
-Here ``!14`` is metadata providing `location information
+Here ``!13`` is metadata providing `location information
 <LangRef.html#dilocation>`_.  In this example, scope is encoded by ``!4``, a
 `subprogram descriptor <LangRef.html#disubprogram>`_.  This way the location
 information attached to the intrinsics indicates that the variable ``X`` is
@@ -373,20 +372,20 @@ Now lets take another example.
 
 .. code-block:: llvm
 
-  call void @llvm.dbg.declare(metadata i32* %Z, metadata !17, metadata !13), !dbg !19
+  call void @llvm.dbg.declare(metadata i32* %Z, metadata !16, metadata !DIExpression()), !dbg !18
     ; [debug line = 5:9] [debug variable = Z]
 
 The third intrinsic ``%llvm.dbg.declare`` encodes debugging information for
-variable ``Z``.  The metadata ``!dbg !19`` attached to the intrinsic provides
+variable ``Z``.  The metadata ``!dbg !18`` attached to the intrinsic provides
 scope information for the variable ``Z``.
 
 .. code-block:: text
 
-  !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5)
-  !19 = !DILocation(line: 5, column: 11, scope: !18)
+  !17 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5)
+  !18 = !DILocation(line: 5, column: 11, scope: !17)
 
-Here ``!19`` indicates that ``Z`` is declared at line number 5 and column
-number 11 inside of lexical scope ``!18``.  The lexical scope itself resides
+Here ``!18`` indicates that ``Z`` is declared at line number 5 and column
+number 11 inside of lexical scope ``!17``.  The lexical scope itself resides
 inside of subprogram ``!4`` described above.
 
 The scope information attached with each instruction provides a straightforward
@@ -802,14 +801,14 @@ presents several 
diff iculties:
     br label %exit, !dbg !26
 
   truebr:
-    call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !24
-    call void @llvm.dbg.value(metadata i32 1, metadata !23, metadata !DIExpression()), !dbg !24
+    call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !23
+    call void @llvm.dbg.value(metadata i32 1, metadata !22, metadata !DIExpression()), !dbg !23
     %value1 = add i32 %input, 1
     br label %bb1
 
   falsebr:
-    call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !24
-    call void @llvm.dbg.value(metadata i32 2, metadata !23, metadata !DIExpression()), !dbg !24
+    call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !23
+    call void @llvm.dbg.value(metadata i32 2, metadata !22, metadata !DIExpression()), !dbg !23
     %value = add i32 %input, 2
     br label %bb1
 
@@ -820,7 +819,7 @@ presents several 
diff iculties:
 Here the 
diff iculties are:
 
 * The control flow is roughly the opposite of basic block order
-* The value of the ``!23`` variable merges into ``%bb1``, but there is no PHI
+* The value of the ``!22`` variable merges into ``%bb1``, but there is no PHI
   node
 
 As mentioned above, the ``llvm.dbg.value`` intrinsics essentially form an
@@ -833,9 +832,9 @@ location, which would lead to a large number of debugging intrinsics being
 generated.
 
 Examining the example above, variable ``!30`` is assigned ``%input`` on both
-conditional paths through the function, while ``!23`` is assigned 
diff ering
+conditional paths through the function, while ``!22`` is assigned 
diff ering
 constant values on either path. Where control flow merges in ``%bb1`` we would
-want ``!30`` to keep its location (``%input``), but ``!23`` to become undefined
+want ``!30`` to keep its location (``%input``), but ``!22`` to become undefined
 as we cannot determine at runtime what value it should have in %bb1 without
 inserting a PHI node. mem2reg does not insert the PHI node to avoid changing
 codegen when debugging is enabled, and does not insert the other dbg.values
@@ -854,7 +853,7 @@ DbgEntityHistoryCalculator) to build a map of each instruction to every
 valid variable location, without the need to consider control flow. From
 the example above, it is otherwise 
diff icult to determine that the location
 of variable ``!30`` should flow "up" into block ``%bb1``, but that the location
-of variable ``!23`` should not flow "down" into the ``%exit`` block.
+of variable ``!22`` should not flow "down" into the ``%exit`` block.
 
 .. _ccxx_frontend:
 

diff  --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index d621c232378c3..2224c28faecf8 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -520,7 +520,8 @@ namespace llvm {
     template <class ParserTy> bool parseMDFieldsImplBody(ParserTy ParseField);
     template <class ParserTy>
     bool parseMDFieldsImpl(ParserTy ParseField, LocTy &ClosingLoc);
-    bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false);
+    bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false,
+                                LocTy DistinctLoc = LocTy());
 
 #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS)                                  \
   bool parse##CLASS(MDNode *&Result, bool IsDistinct);

diff  --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 7a4152994b980..00396103f473b 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -39,26 +39,39 @@
 // Helper macros for defining get() overrides.
 #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__
 #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS
-#define DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)              \
+#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS)                                 \
+  static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) {  \
+    return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued);          \
+  }
+#define DEFINE_MDNODE_GET_IF_EXISTS(CLASS, FORMAL, ARGS)                       \
+  static CLASS *getIfExists(LLVMContext &Context,                              \
+                            DEFINE_MDNODE_GET_UNPACK(FORMAL)) {                \
+    return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued,           \
+                   /* ShouldCreate */ false);                                  \
+  }
+#define DEFINE_MDNODE_GET_DISTINCT(CLASS, FORMAL, ARGS)                        \
   static CLASS *getDistinct(LLVMContext &Context,                              \
                             DEFINE_MDNODE_GET_UNPACK(FORMAL)) {                \
     return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct);         \
-  }                                                                            \
+  }
+#define DEFINE_MDNODE_GET_TEMPORARY(CLASS, FORMAL, ARGS)                       \
   static Temp##CLASS getTemporary(LLVMContext &Context,                        \
                                   DEFINE_MDNODE_GET_UNPACK(FORMAL)) {          \
     return Temp##CLASS(                                                        \
         getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary));          \
   }
-#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS)                                 \
-  static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) {  \
-    return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued);          \
-  }                                                                            \
-  static CLASS *getIfExists(LLVMContext &Context,                              \
-                            DEFINE_MDNODE_GET_UNPACK(FORMAL)) {                \
-    return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued,           \
-                   /* ShouldCreate */ false);                                  \
-  }                                                                            \
-  DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)
+#define DEFINE_ALL_MDNODE_GET_METHODS(CLASS, FORMAL, ARGS)                     \
+  DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS)                                       \
+  DEFINE_MDNODE_GET_IF_EXISTS(CLASS, FORMAL, ARGS)                             \
+  DEFINE_MDNODE_GET_DISTINCT(CLASS, FORMAL, ARGS)                              \
+  DEFINE_MDNODE_GET_TEMPORARY(CLASS, FORMAL, ARGS)
+#define DEFINE_ALWAYS_DISTINCT_MDNODE_GET_METHODS(CLASS, FORMAL, ARGS)         \
+  DEFINE_MDNODE_GET_DISTINCT(CLASS, FORMAL, ARGS)                              \
+  DEFINE_MDNODE_GET_TEMPORARY(CLASS, FORMAL, ARGS)
+#define DEFINE_ALWAYS_UNIQUED_MDNODE_GET_METHODS(CLASS, FORMAL, ARGS)          \
+  DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS)                                       \
+  DEFINE_MDNODE_GET_IF_EXISTS(CLASS, FORMAL, ARGS)                             \
+  DEFINE_MDNODE_GET_TEMPORARY(CLASS, FORMAL, ARGS)
 
 namespace llvm {
 
@@ -256,12 +269,14 @@ class GenericDINode : public DINode {
 public:
   unsigned getHash() const { return SubclassData32; }
 
-  DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header,
-                                    ArrayRef<Metadata *> DwarfOps),
-                    (Tag, Header, DwarfOps))
-  DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header,
-                                    ArrayRef<Metadata *> DwarfOps),
-                    (Tag, Header, DwarfOps))
+  DEFINE_ALL_MDNODE_GET_METHODS(GenericDINode,
+                                (unsigned Tag, StringRef Header,
+                                 ArrayRef<Metadata *> DwarfOps),
+                                (Tag, Header, DwarfOps))
+  DEFINE_ALL_MDNODE_GET_METHODS(GenericDINode,
+                                (unsigned Tag, MDString *Header,
+                                 ArrayRef<Metadata *> DwarfOps),
+                                (Tag, Header, DwarfOps))
 
   /// Return a (temporary) clone of this.
   TempGenericDINode clone() const { return cloneImpl(); }
@@ -321,16 +336,18 @@ class DISubrange : public DINode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0),
-                    (Count, LowerBound))
+  DEFINE_ALL_MDNODE_GET_METHODS(DISubrange,
+                                (int64_t Count, int64_t LowerBound = 0),
+                                (Count, LowerBound))
 
-  DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0),
-                    (CountNode, LowerBound))
+  DEFINE_ALL_MDNODE_GET_METHODS(DISubrange,
+                                (Metadata * CountNode, int64_t LowerBound = 0),
+                                (CountNode, LowerBound))
 
-  DEFINE_MDNODE_GET(DISubrange,
-                    (Metadata * CountNode, Metadata *LowerBound,
-                     Metadata *UpperBound, Metadata *Stride),
-                    (CountNode, LowerBound, UpperBound, Stride))
+  DEFINE_ALL_MDNODE_GET_METHODS(DISubrange,
+                                (Metadata * CountNode, Metadata *LowerBound,
+                                 Metadata *UpperBound, Metadata *Stride),
+                                (CountNode, LowerBound, UpperBound, Stride))
 
   TempDISubrange clone() const { return cloneImpl(); }
 
@@ -381,10 +398,10 @@ class DIGenericSubrange : public DINode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIGenericSubrange,
-                    (Metadata * CountNode, Metadata *LowerBound,
-                     Metadata *UpperBound, Metadata *Stride),
-                    (CountNode, LowerBound, UpperBound, Stride))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIGenericSubrange,
+                                (Metadata * CountNode, Metadata *LowerBound,
+                                 Metadata *UpperBound, Metadata *Stride),
+                                (CountNode, LowerBound, UpperBound, Stride))
 
   TempDIGenericSubrange clone() const { return cloneImpl(); }
 
@@ -441,18 +458,18 @@ class DIEnumerator : public DINode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIEnumerator,
-                    (int64_t Value, bool IsUnsigned, StringRef Name),
-                    (APInt(64, Value, !IsUnsigned), IsUnsigned, Name))
-  DEFINE_MDNODE_GET(DIEnumerator,
-                    (int64_t Value, bool IsUnsigned, MDString *Name),
-                    (APInt(64, Value, !IsUnsigned), IsUnsigned, Name))
-  DEFINE_MDNODE_GET(DIEnumerator,
-                    (APInt Value, bool IsUnsigned, StringRef Name),
-                    (Value, IsUnsigned, Name))
-  DEFINE_MDNODE_GET(DIEnumerator,
-                    (APInt Value, bool IsUnsigned, MDString *Name),
-                    (Value, IsUnsigned, Name))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name),
+      (APInt(64, Value, !IsUnsigned), IsUnsigned, Name))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name),
+      (APInt(64, Value, !IsUnsigned), IsUnsigned, Name))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIEnumerator,
+                                (APInt Value, bool IsUnsigned, StringRef Name),
+                                (Value, IsUnsigned, Name))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIEnumerator,
+                                (APInt Value, bool IsUnsigned, MDString *Name),
+                                (Value, IsUnsigned, Name))
 
   TempDIEnumerator clone() const { return cloneImpl(); }
 
@@ -600,14 +617,16 @@ class DIFile : public DIScope {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory,
-                             Optional<ChecksumInfo<StringRef>> CS = None,
-                             Optional<StringRef> Source = None),
-                    (Filename, Directory, CS, Source))
-  DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory,
-                             Optional<ChecksumInfo<MDString *>> CS = None,
-                             Optional<MDString *> Source = None),
-                    (Filename, Directory, CS, Source))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIFile,
+                                (StringRef Filename, StringRef Directory,
+                                 Optional<ChecksumInfo<StringRef>> CS = None,
+                                 Optional<StringRef> Source = None),
+                                (Filename, Directory, CS, Source))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIFile,
+                                (MDString * Filename, MDString *Directory,
+                                 Optional<ChecksumInfo<MDString *>> CS = None,
+                                 Optional<MDString *> Source = None),
+                                (Filename, Directory, CS, Source))
 
   TempDIFile clone() const { return cloneImpl(); }
 
@@ -801,22 +820,28 @@ class DIBasicType : public DIType {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
-                    (Tag, Name, 0, 0, 0, FlagZero))
-  DEFINE_MDNODE_GET(DIBasicType,
-                    (unsigned Tag, StringRef Name, uint64_t SizeInBits),
-                    (Tag, Name, SizeInBits, 0, 0, FlagZero))
-  DEFINE_MDNODE_GET(DIBasicType,
-                    (unsigned Tag, MDString *Name, uint64_t SizeInBits),
-                    (Tag, Name, SizeInBits, 0, 0, FlagZero))
-  DEFINE_MDNODE_GET(DIBasicType,
-                    (unsigned Tag, StringRef Name, uint64_t SizeInBits,
-                     uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
-                    (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
-  DEFINE_MDNODE_GET(DIBasicType,
-                    (unsigned Tag, MDString *Name, uint64_t SizeInBits,
-                     uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
-                    (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIBasicType, (unsigned Tag, StringRef Name),
+                                (Tag, Name, 0, 0, 0, FlagZero))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIBasicType,
+                                (unsigned Tag, StringRef Name,
+                                 uint64_t SizeInBits),
+                                (Tag, Name, SizeInBits, 0, 0, FlagZero))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIBasicType,
+                                (unsigned Tag, MDString *Name,
+                                 uint64_t SizeInBits),
+                                (Tag, Name, SizeInBits, 0, 0, FlagZero))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIBasicType,
+                                (unsigned Tag, StringRef Name,
+                                 uint64_t SizeInBits, uint32_t AlignInBits,
+                                 unsigned Encoding, DIFlags Flags),
+                                (Tag, Name, SizeInBits, AlignInBits, Encoding,
+                                 Flags))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIBasicType,
+                                (unsigned Tag, MDString *Name,
+                                 uint64_t SizeInBits, uint32_t AlignInBits,
+                                 unsigned Encoding, DIFlags Flags),
+                                (Tag, Name, SizeInBits, AlignInBits, Encoding,
+                                 Flags))
 
   TempDIBasicType clone() const { return cloneImpl(); }
 
@@ -870,22 +895,25 @@ class DIStringType : public DIType {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIStringType,
-                    (unsigned Tag, StringRef Name, uint64_t SizeInBits,
-                     uint32_t AlignInBits),
-                    (Tag, Name, nullptr, nullptr, SizeInBits, AlignInBits, 0))
-  DEFINE_MDNODE_GET(DIStringType,
-                    (unsigned Tag, MDString *Name, Metadata *StringLength,
-                     Metadata *StringLengthExp, uint64_t SizeInBits,
-                     uint32_t AlignInBits, unsigned Encoding),
-                    (Tag, Name, StringLength, StringLengthExp, SizeInBits,
-                     AlignInBits, Encoding))
-  DEFINE_MDNODE_GET(DIStringType,
-                    (unsigned Tag, StringRef Name, Metadata *StringLength,
-                     Metadata *StringLengthExp, uint64_t SizeInBits,
-                     uint32_t AlignInBits, unsigned Encoding),
-                    (Tag, Name, StringLength, StringLengthExp, SizeInBits,
-                     AlignInBits, Encoding))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIStringType,
+                                (unsigned Tag, StringRef Name,
+                                 uint64_t SizeInBits, uint32_t AlignInBits),
+                                (Tag, Name, nullptr, nullptr, SizeInBits,
+                                 AlignInBits, 0))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIStringType,
+                                (unsigned Tag, MDString *Name,
+                                 Metadata *StringLength,
+                                 Metadata *StringLengthExp, uint64_t SizeInBits,
+                                 uint32_t AlignInBits, unsigned Encoding),
+                                (Tag, Name, StringLength, StringLengthExp,
+                                 SizeInBits, AlignInBits, Encoding))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIStringType,
+                                (unsigned Tag, StringRef Name,
+                                 Metadata *StringLength,
+                                 Metadata *StringLengthExp, uint64_t SizeInBits,
+                                 uint32_t AlignInBits, unsigned Encoding),
+                                (Tag, Name, StringLength, StringLengthExp,
+                                 SizeInBits, AlignInBits, Encoding))
 
   TempDIStringType clone() const { return cloneImpl(); }
 
@@ -959,27 +987,24 @@ class DIDerivedType : public DIType {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIDerivedType,
-                    (unsigned Tag, MDString *Name, Metadata *File,
-                     unsigned Line, Metadata *Scope, Metadata *BaseType,
-                     uint64_t SizeInBits, uint32_t AlignInBits,
-                     uint64_t OffsetInBits,
-                     Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
-                     Metadata *ExtraData = nullptr,
-                     Metadata *Annotations = nullptr),
-                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
-                     AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
-                     ExtraData, Annotations))
-  DEFINE_MDNODE_GET(DIDerivedType,
-                    (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
-                     DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
-                     uint32_t AlignInBits, uint64_t OffsetInBits,
-                     Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
-                     Metadata *ExtraData = nullptr,
-                     DINodeArray Annotations = nullptr),
-                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
-                     AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
-                     ExtraData, Annotations))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIDerivedType,
+      (unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
+       Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
+       uint32_t AlignInBits, uint64_t OffsetInBits,
+       Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
+       Metadata *ExtraData = nullptr, Metadata *Annotations = nullptr),
+      (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+       OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIDerivedType,
+      (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
+       DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
+       uint32_t AlignInBits, uint64_t OffsetInBits,
+       Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
+       Metadata *ExtraData = nullptr, DINodeArray Annotations = nullptr),
+      (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+       OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations))
 
   TempDIDerivedType clone() const { return cloneImpl(); }
 
@@ -1120,7 +1145,7 @@ class DICompositeType : public DIType {
   }
 
 public:
-  DEFINE_MDNODE_GET(
+  DEFINE_ALL_MDNODE_GET_METHODS(
       DICompositeType,
       (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
        DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
@@ -1135,7 +1160,7 @@ class DICompositeType : public DIType {
        OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
        Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,
        Annotations))
-  DEFINE_MDNODE_GET(
+  DEFINE_ALL_MDNODE_GET_METHODS(
       DICompositeType,
       (unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
        Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
@@ -1309,12 +1334,14 @@ class DISubroutineType : public DIType {
   }
 
 public:
-  DEFINE_MDNODE_GET(DISubroutineType,
-                    (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray),
-                    (Flags, CC, TypeArray))
-  DEFINE_MDNODE_GET(DISubroutineType,
-                    (DIFlags Flags, uint8_t CC, Metadata *TypeArray),
-                    (Flags, CC, TypeArray))
+  DEFINE_ALL_MDNODE_GET_METHODS(DISubroutineType,
+                                (DIFlags Flags, uint8_t CC,
+                                 DITypeRefArray TypeArray),
+                                (Flags, CC, TypeArray))
+  DEFINE_ALL_MDNODE_GET_METHODS(DISubroutineType,
+                                (DIFlags Flags, uint8_t CC,
+                                 Metadata *TypeArray),
+                                (Flags, CC, TypeArray))
 
   TempDISubroutineType clone() const { return cloneImpl(); }
 
@@ -1429,7 +1456,7 @@ class DICompileUnit : public DIScope {
   static void get() = delete;
   static void getIfExists() = delete;
 
-  DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(
+  DEFINE_ALWAYS_DISTINCT_MDNODE_GET_METHODS(
       DICompileUnit,
       (unsigned SourceLanguage, DIFile *File, StringRef Producer,
        bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
@@ -1445,7 +1472,7 @@ class DICompileUnit : public DIScope {
        GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,
        DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress,
        SysRoot, SDK))
-  DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(
+  DEFINE_ALWAYS_DISTINCT_MDNODE_GET_METHODS(
       DICompileUnit,
       (unsigned SourceLanguage, Metadata *File, MDString *Producer,
        bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,
@@ -1609,15 +1636,17 @@ class DILocation : public MDNode {
   // Disallow replacing operands.
   void replaceOperandWith(unsigned I, Metadata *New) = delete;
 
-  DEFINE_MDNODE_GET(DILocation,
-                    (unsigned Line, unsigned Column, Metadata *Scope,
-                     Metadata *InlinedAt = nullptr, bool ImplicitCode = false),
-                    (Line, Column, Scope, InlinedAt, ImplicitCode))
-  DEFINE_MDNODE_GET(DILocation,
-                    (unsigned Line, unsigned Column, DILocalScope *Scope,
-                     DILocation *InlinedAt = nullptr,
-                     bool ImplicitCode = false),
-                    (Line, Column, Scope, InlinedAt, ImplicitCode))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILocation,
+                                (unsigned Line, unsigned Column,
+                                 Metadata *Scope, Metadata *InlinedAt = nullptr,
+                                 bool ImplicitCode = false),
+                                (Line, Column, Scope, InlinedAt, ImplicitCode))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILocation,
+                                (unsigned Line, unsigned Column,
+                                 DILocalScope *Scope,
+                                 DILocation *InlinedAt = nullptr,
+                                 bool ImplicitCode = false),
+                                (Line, Column, Scope, InlinedAt, ImplicitCode))
 
   /// Return a (temporary) clone of this.
   TempDILocation clone() const { return cloneImpl(); }
@@ -1922,7 +1951,7 @@ class DISubprogram : public DILocalScope {
   }
 
 public:
-  DEFINE_MDNODE_GET(
+  DEFINE_ALL_MDNODE_GET_METHODS(
       DISubprogram,
       (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File,
        unsigned Line, DISubroutineType *Type, unsigned ScopeLine,
@@ -1935,7 +1964,7 @@ class DISubprogram : public DILocalScope {
        VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams,
        Declaration, RetainedNodes, ThrownTypes, Annotations))
 
-  DEFINE_MDNODE_GET(
+  DEFINE_ALL_MDNODE_GET_METHODS(
       DISubprogram,
       (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
        unsigned Line, Metadata *Type, unsigned ScopeLine,
@@ -2139,12 +2168,14 @@ class DILexicalBlock : public DILexicalBlockBase {
   }
 
 public:
-  DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File,
-                                     unsigned Line, unsigned Column),
-                    (Scope, File, Line, Column))
-  DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File,
-                                     unsigned Line, unsigned Column),
-                    (Scope, File, Line, Column))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILexicalBlock,
+                                (DILocalScope * Scope, DIFile *File,
+                                 unsigned Line, unsigned Column),
+                                (Scope, File, Line, Column))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILexicalBlock,
+                                (Metadata * Scope, Metadata *File,
+                                 unsigned Line, unsigned Column),
+                                (Scope, File, Line, Column))
 
   TempDILexicalBlock clone() const { return cloneImpl(); }
 
@@ -2188,12 +2219,14 @@ class DILexicalBlockFile : public DILexicalBlockBase {
   }
 
 public:
-  DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File,
-                                         unsigned Discriminator),
-                    (Scope, File, Discriminator))
-  DEFINE_MDNODE_GET(DILexicalBlockFile,
-                    (Metadata * Scope, Metadata *File, unsigned Discriminator),
-                    (Scope, File, Discriminator))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILexicalBlockFile,
+                                (DILocalScope * Scope, DIFile *File,
+                                 unsigned Discriminator),
+                                (Scope, File, Discriminator))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILexicalBlockFile,
+                                (Metadata * Scope, Metadata *File,
+                                 unsigned Discriminator),
+                                (Scope, File, Discriminator))
 
   TempDILexicalBlockFile clone() const { return cloneImpl(); }
   unsigned getDiscriminator() const { return Discriminator; }
@@ -2302,12 +2335,14 @@ class DINamespace : public DIScope {
   }
 
 public:
-  DEFINE_MDNODE_GET(DINamespace,
-                    (DIScope *Scope, StringRef Name, bool ExportSymbols),
-                    (Scope, Name, ExportSymbols))
-  DEFINE_MDNODE_GET(DINamespace,
-                    (Metadata *Scope, MDString *Name, bool ExportSymbols),
-                    (Scope, Name, ExportSymbols))
+  DEFINE_ALL_MDNODE_GET_METHODS(DINamespace,
+                                (DIScope * Scope, StringRef Name,
+                                 bool ExportSymbols),
+                                (Scope, Name, ExportSymbols))
+  DEFINE_ALL_MDNODE_GET_METHODS(DINamespace,
+                                (Metadata * Scope, MDString *Name,
+                                 bool ExportSymbols),
+                                (Scope, Name, ExportSymbols))
 
   TempDINamespace clone() const { return cloneImpl(); }
 
@@ -2361,20 +2396,20 @@ class DIModule : public DIScope {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIModule,
-                    (DIFile * File, DIScope *Scope, StringRef Name,
-                     StringRef ConfigurationMacros, StringRef IncludePath,
-                     StringRef APINotesFile, unsigned LineNo,
-                     bool IsDecl = false),
-                    (File, Scope, Name, ConfigurationMacros, IncludePath,
-                     APINotesFile, LineNo, IsDecl))
-  DEFINE_MDNODE_GET(DIModule,
-                    (Metadata * File, Metadata *Scope, MDString *Name,
-                     MDString *ConfigurationMacros, MDString *IncludePath,
-                     MDString *APINotesFile, unsigned LineNo,
-                     bool IsDecl = false),
-                    (File, Scope, Name, ConfigurationMacros, IncludePath,
-                     APINotesFile, LineNo, IsDecl))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIModule,
+                                (DIFile * File, DIScope *Scope, StringRef Name,
+                                 StringRef ConfigurationMacros,
+                                 StringRef IncludePath, StringRef APINotesFile,
+                                 unsigned LineNo, bool IsDecl = false),
+                                (File, Scope, Name, ConfigurationMacros,
+                                 IncludePath, APINotesFile, LineNo, IsDecl))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIModule,
+                                (Metadata * File, Metadata *Scope,
+                                 MDString *Name, MDString *ConfigurationMacros,
+                                 MDString *IncludePath, MDString *APINotesFile,
+                                 unsigned LineNo, bool IsDecl = false),
+                                (File, Scope, Name, ConfigurationMacros,
+                                 IncludePath, APINotesFile, LineNo, IsDecl))
 
   TempDIModule clone() const { return cloneImpl(); }
 
@@ -2451,12 +2486,13 @@ class DITemplateTypeParameter : public DITemplateParameter {
   }
 
 public:
-  DEFINE_MDNODE_GET(DITemplateTypeParameter,
-                    (StringRef Name, DIType *Type, bool IsDefault),
-                    (Name, Type, IsDefault))
-  DEFINE_MDNODE_GET(DITemplateTypeParameter,
-                    (MDString *Name, Metadata *Type, bool IsDefault),
-                    (Name, Type, IsDefault))
+  DEFINE_ALL_MDNODE_GET_METHODS(DITemplateTypeParameter,
+                                (StringRef Name, DIType *Type, bool IsDefault),
+                                (Name, Type, IsDefault))
+  DEFINE_ALL_MDNODE_GET_METHODS(DITemplateTypeParameter,
+                                (MDString * Name, Metadata *Type,
+                                 bool IsDefault),
+                                (Name, Type, IsDefault))
 
   TempDITemplateTypeParameter clone() const { return cloneImpl(); }
 
@@ -2496,14 +2532,14 @@ class DITemplateValueParameter : public DITemplateParameter {
   }
 
 public:
-  DEFINE_MDNODE_GET(DITemplateValueParameter,
-                    (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault,
-                     Metadata *Value),
-                    (Tag, Name, Type, IsDefault, Value))
-  DEFINE_MDNODE_GET(DITemplateValueParameter,
-                    (unsigned Tag, MDString *Name, Metadata *Type,
-                     bool IsDefault, Metadata *Value),
-                    (Tag, Name, Type, IsDefault, Value))
+  DEFINE_ALL_MDNODE_GET_METHODS(DITemplateValueParameter,
+                                (unsigned Tag, StringRef Name, DIType *Type,
+                                 bool IsDefault, Metadata *Value),
+                                (Tag, Name, Type, IsDefault, Value))
+  DEFINE_ALL_MDNODE_GET_METHODS(DITemplateValueParameter,
+                                (unsigned Tag, MDString *Name, Metadata *Type,
+                                 bool IsDefault, Metadata *Value),
+                                (Tag, Name, Type, IsDefault, Value))
 
   TempDITemplateValueParameter clone() const { return cloneImpl(); }
 
@@ -2603,7 +2639,9 @@ class DIExpression : public MDNode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements))
+  DEFINE_ALWAYS_UNIQUED_MDNODE_GET_METHODS(DIExpression,
+                                           (ArrayRef<uint64_t> Elements),
+                                           (Elements))
 
   TempDIExpression clone() const { return cloneImpl(); }
 
@@ -2987,26 +3025,22 @@ class DIGlobalVariable : public DIVariable {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIGlobalVariable,
-                    (DIScope * Scope, StringRef Name, StringRef LinkageName,
-                     DIFile *File, unsigned Line, DIType *Type,
-                     bool IsLocalToUnit, bool IsDefinition,
-                     DIDerivedType *StaticDataMemberDeclaration,
-                     MDTuple *TemplateParams, uint32_t AlignInBits,
-                     DINodeArray Annotations),
-                    (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
-                     IsDefinition, StaticDataMemberDeclaration, TemplateParams,
-                     AlignInBits, Annotations))
-  DEFINE_MDNODE_GET(DIGlobalVariable,
-                    (Metadata * Scope, MDString *Name, MDString *LinkageName,
-                     Metadata *File, unsigned Line, Metadata *Type,
-                     bool IsLocalToUnit, bool IsDefinition,
-                     Metadata *StaticDataMemberDeclaration,
-                     Metadata *TemplateParams, uint32_t AlignInBits,
-                     Metadata *Annotations),
-                    (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
-                     IsDefinition, StaticDataMemberDeclaration, TemplateParams,
-                     AlignInBits, Annotations))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIGlobalVariable,
+      (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File,
+       unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition,
+       DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams,
+       uint32_t AlignInBits, DINodeArray Annotations),
+      (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
+       StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIGlobalVariable,
+      (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
+       unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
+       Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,
+       uint32_t AlignInBits, Metadata *Annotations),
+      (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
+       StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations))
 
   TempDIGlobalVariable clone() const { return cloneImpl(); }
 
@@ -3062,14 +3096,15 @@ class DICommonBlock : public DIScope {
   }
 
 public:
-  DEFINE_MDNODE_GET(DICommonBlock,
-                    (DIScope *Scope, DIGlobalVariable *Decl, StringRef Name,
-                     DIFile *File, unsigned LineNo),
-                    (Scope, Decl, Name, File, LineNo))
-  DEFINE_MDNODE_GET(DICommonBlock,
-                    (Metadata *Scope, Metadata *Decl, MDString *Name,
-                     Metadata *File, unsigned LineNo),
-                    (Scope, Decl, Name, File, LineNo))
+  DEFINE_ALL_MDNODE_GET_METHODS(DICommonBlock,
+                                (DIScope * Scope, DIGlobalVariable *Decl,
+                                 StringRef Name, DIFile *File, unsigned LineNo),
+                                (Scope, Decl, Name, File, LineNo))
+  DEFINE_ALL_MDNODE_GET_METHODS(DICommonBlock,
+                                (Metadata * Scope, Metadata *Decl,
+                                 MDString *Name, Metadata *File,
+                                 unsigned LineNo),
+                                (Scope, Decl, Name, File, LineNo))
 
   TempDICommonBlock clone() const { return cloneImpl(); }
 
@@ -3132,18 +3167,20 @@ class DILocalVariable : public DIVariable {
   }
 
 public:
-  DEFINE_MDNODE_GET(DILocalVariable,
-                    (DILocalScope * Scope, StringRef Name, DIFile *File,
-                     unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags,
-                     uint32_t AlignInBits, DINodeArray Annotations),
-                    (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits,
-                     Annotations))
-  DEFINE_MDNODE_GET(DILocalVariable,
-                    (Metadata * Scope, MDString *Name, Metadata *File,
-                     unsigned Line, Metadata *Type, unsigned Arg,
-                     DIFlags Flags, uint32_t AlignInBits, Metadata *Annotations),
-                    (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits,
-                     Annotations))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILocalVariable,
+                                (DILocalScope * Scope, StringRef Name,
+                                 DIFile *File, unsigned Line, DIType *Type,
+                                 unsigned Arg, DIFlags Flags,
+                                 uint32_t AlignInBits, DINodeArray Annotations),
+                                (Scope, Name, File, Line, Type, Arg, Flags,
+                                 AlignInBits, Annotations))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILocalVariable,
+                                (Metadata * Scope, MDString *Name,
+                                 Metadata *File, unsigned Line, Metadata *Type,
+                                 unsigned Arg, DIFlags Flags,
+                                 uint32_t AlignInBits, Metadata *Annotations),
+                                (Scope, Name, File, Line, Type, Arg, Flags,
+                                 AlignInBits, Annotations))
 
   TempDILocalVariable clone() const { return cloneImpl(); }
 
@@ -3211,14 +3248,14 @@ class DILabel : public DINode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DILabel,
-                    (DILocalScope * Scope, StringRef Name, DIFile *File,
-                     unsigned Line),
-                    (Scope, Name, File, Line))
-  DEFINE_MDNODE_GET(DILabel,
-                    (Metadata * Scope, MDString *Name, Metadata *File,
-                     unsigned Line),
-                    (Scope, Name, File, Line))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILabel,
+                                (DILocalScope * Scope, StringRef Name,
+                                 DIFile *File, unsigned Line),
+                                (Scope, Name, File, Line))
+  DEFINE_ALL_MDNODE_GET_METHODS(DILabel,
+                                (Metadata * Scope, MDString *Name,
+                                 Metadata *File, unsigned Line),
+                                (Scope, Name, File, Line))
 
   TempDILabel clone() const { return cloneImpl(); }
 
@@ -3286,18 +3323,18 @@ class DIObjCProperty : public DINode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIObjCProperty,
-                    (StringRef Name, DIFile *File, unsigned Line,
-                     StringRef GetterName, StringRef SetterName,
-                     unsigned Attributes, DIType *Type),
-                    (Name, File, Line, GetterName, SetterName, Attributes,
-                     Type))
-  DEFINE_MDNODE_GET(DIObjCProperty,
-                    (MDString * Name, Metadata *File, unsigned Line,
-                     MDString *GetterName, MDString *SetterName,
-                     unsigned Attributes, Metadata *Type),
-                    (Name, File, Line, GetterName, SetterName, Attributes,
-                     Type))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIObjCProperty,
+                                (StringRef Name, DIFile *File, unsigned Line,
+                                 StringRef GetterName, StringRef SetterName,
+                                 unsigned Attributes, DIType *Type),
+                                (Name, File, Line, GetterName, SetterName,
+                                 Attributes, Type))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIObjCProperty,
+                                (MDString * Name, Metadata *File, unsigned Line,
+                                 MDString *GetterName, MDString *SetterName,
+                                 unsigned Attributes, Metadata *Type),
+                                (Name, File, Line, GetterName, SetterName,
+                                 Attributes, Type))
 
   TempDIObjCProperty clone() const { return cloneImpl(); }
 
@@ -3364,16 +3401,16 @@ class DIImportedEntity : public DINode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIImportedEntity,
-                    (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File,
-                     unsigned Line, StringRef Name = "",
-                     DINodeArray Elements = nullptr),
-                    (Tag, Scope, Entity, File, Line, Name, Elements))
-  DEFINE_MDNODE_GET(DIImportedEntity,
-                    (unsigned Tag, Metadata *Scope, Metadata *Entity,
-                     Metadata *File, unsigned Line, MDString *Name,
-                     Metadata *Elements = nullptr),
-                    (Tag, Scope, Entity, File, Line, Name, Elements))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIImportedEntity,
+      (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File,
+       unsigned Line, StringRef Name = "", DINodeArray Elements = nullptr),
+      (Tag, Scope, Entity, File, Line, Name, Elements))
+  DEFINE_ALL_MDNODE_GET_METHODS(
+      DIImportedEntity,
+      (unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File,
+       unsigned Line, MDString *Name, Metadata *Elements = nullptr),
+      (Tag, Scope, Entity, File, Line, Name, Elements))
 
   TempDIImportedEntity clone() const { return cloneImpl(); }
 
@@ -3416,9 +3453,9 @@ class DIGlobalVariableExpression : public MDNode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIGlobalVariableExpression,
-                    (Metadata * Variable, Metadata *Expression),
-                    (Variable, Expression))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIGlobalVariableExpression,
+                                (Metadata * Variable, Metadata *Expression),
+                                (Variable, Expression))
 
   TempDIGlobalVariableExpression clone() const { return cloneImpl(); }
 
@@ -3515,12 +3552,14 @@ class DIMacro : public DIMacroNode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, StringRef Name,
-                              StringRef Value = ""),
-                    (MIType, Line, Name, Value))
-  DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, MDString *Name,
-                              MDString *Value),
-                    (MIType, Line, Name, Value))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIMacro,
+                                (unsigned MIType, unsigned Line, StringRef Name,
+                                 StringRef Value = ""),
+                                (MIType, Line, Name, Value))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIMacro,
+                                (unsigned MIType, unsigned Line, MDString *Name,
+                                 MDString *Value),
+                                (MIType, Line, Name, Value))
 
   TempDIMacro clone() const { return cloneImpl(); }
 
@@ -3566,12 +3605,14 @@ class DIMacroFile : public DIMacroNode {
   }
 
 public:
-  DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, DIFile *File,
-                                  DIMacroNodeArray Elements),
-                    (MIType, Line, File, Elements))
-  DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line,
-                                  Metadata *File, Metadata *Elements),
-                    (MIType, Line, File, Elements))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIMacroFile,
+                                (unsigned MIType, unsigned Line, DIFile *File,
+                                 DIMacroNodeArray Elements),
+                                (MIType, Line, File, Elements))
+  DEFINE_ALL_MDNODE_GET_METHODS(DIMacroFile,
+                                (unsigned MIType, unsigned Line, Metadata *File,
+                                 Metadata *Elements),
+                                (MIType, Line, File, Elements))
 
   TempDIMacroFile clone() const { return cloneImpl(); }
 
@@ -3629,7 +3670,9 @@ class DIArgList : public MDNode {
   void dropAllReferences();
 
 public:
-  DEFINE_MDNODE_GET(DIArgList, (ArrayRef<ValueAsMetadata *> Args), (Args))
+  DEFINE_ALWAYS_UNIQUED_MDNODE_GET_METHODS(DIArgList,
+                                           (ArrayRef<ValueAsMetadata *> Args),
+                                           (Args))
 
   TempDIArgList clone() const { return cloneImpl(); }
 
@@ -3733,5 +3776,11 @@ template <> struct DenseMapInfo<DebugVariable> {
 #undef DEFINE_MDNODE_GET_UNPACK_IMPL
 #undef DEFINE_MDNODE_GET_UNPACK
 #undef DEFINE_MDNODE_GET
+#undef DEFINE_MDNODE_GET_IF_EXISTS
+#undef DEFINE_MDNODE_GET_DISTINCT
+#undef DEFINE_MDNODE_GET_TEMPORARY
+#undef DEFINE_ALL_MDNODE_GET_METHODS
+#undef DEFINE_ALWAYS_DISTINCT_MDNODE_GET_METHODS
+#undef DEFINE_ALWAYS_UNIQUED_MDNODE_GET_METHODS
 
 #endif // LLVM_IR_DEBUGINFOMETADATA_H

diff  --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index bbf349e6b508c..fdef80724de52 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -8,12 +8,39 @@
 //
 // Macros for running through all types of metadata.
 //
+// Definitions for terms used to describe metadata include:
+//
+// * BRANCH: refers to an "abstract" metadata kind, which exists only in the
+//   C++ class hierarchy. These cannot appear directly in IR/bitcode.
+// * LEAF: refers to a "concrete" metadata kind. These can appear directly in
+//   IR/bitcode.
+// * SPECIALIZED: refers to non-MDTuple MDNodes, i.e. those that use the
+//   syntax "!CLASS(...)" in IR.
+// * UNIQUABLE: refers to nodes which can use uniqued, distinct, or temporary
+//   storage without any restrictions.
+// * UNIQUED: refers to nodes which must use uniqued or temporary storage.
+// * DISTINCT: refers to nodes which must use distinct or temporary storage.
+//
+// In LLVM IR, UNIQUABLE and DISTINCT nodes must be referred to by MDNode ID,
+// as in `!0`, whereas UNIQUED nodes canonically appear inline at each use, as
+// in `DIExpression(...)`. This is because `distinct` nodes maintain their
+// identity irrespective of contents, making the inline syntax ambiguous in
+// some cases.
+//
+// Note: UNIQUABLE, UNIQUED, and DISTINCT are mutually exclusive. For example,
+// code which intends to consider all nodes which can use uniqued storage must
+// consider both UNIQUABLE and UNIQUED nodes.
+//
 //===----------------------------------------------------------------------===//
 
 #if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF ||               \
       defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF ||          \
-      defined HANDLE_MDNODE_LEAF_UNIQUABLE || defined HANDLE_MDNODE_BRANCH ||  \
+      defined HANDLE_MDNODE_LEAF_UNIQUABLE ||                                  \
+      defined HANDLE_MDNODE_LEAF_UNIQUED ||                                    \
+      defined HANDLE_MDNODE_LEAF_DISTINCT || defined HANDLE_MDNODE_BRANCH ||   \
       defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE ||                      \
+      defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED ||                        \
+      defined HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT ||                       \
       defined HANDLE_SPECIALIZED_MDNODE_LEAF ||                                \
       defined HANDLE_SPECIALIZED_MDNODE_BRANCH)
 #error "Missing macro definition of HANDLE_METADATA*"
@@ -34,7 +61,7 @@
 #define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS)
 #endif
 
-// Handler for specialized and uniquable leaf nodes under MDNode.  Defers to
+// Handler for specialized and uniquable leaf nodes under MDNode. Defers to
 // HANDLE_MDNODE_LEAF_UNIQUABLE if it's defined, otherwise to
 // HANDLE_SPECIALIZED_MDNODE_LEAF.
 #ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE
@@ -47,11 +74,47 @@
 #endif
 #endif
 
-// Handler for leaf nodes under MDNode.
+// Handler for specialized and always-uniqued leaf nodes under MDNode. Defers to
+// HANDLE_MDNODE_LEAF_UNIQUED if it's defined, otherwise to
+// HANDLE_SPECIALIZED_MDNODE_LEAF.
+#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED
+#ifdef HANDLE_MDNODE_LEAF_UNIQUED
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(CLASS)                        \
+  HANDLE_MDNODE_LEAF_UNIQUED(CLASS)
+#else
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(CLASS)                        \
+  HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS)
+#endif
+#endif
+
+// Handler for specialized and always-distinct leaf nodes under MDNode. Defers
+// to HANDLE_MDNODE_LEAF_DISTINCT if it's defined, otherwise to
+// HANDLE_SPECIALIZED_MDNODE_LEAF.
+#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT
+#ifdef HANDLE_MDNODE_LEAF_DISTINCT
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(CLASS)                        \
+  HANDLE_MDNODE_LEAF_DISTINCT(CLASS)
+#else
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(CLASS)                        \
+  HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS)
+#endif
+#endif
+
+// Handler for uniquable leaf nodes under MDNode.
 #ifndef HANDLE_MDNODE_LEAF_UNIQUABLE
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) HANDLE_MDNODE_LEAF(CLASS)
 #endif
 
+// Handler for uniqued leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_LEAF_UNIQUED
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#endif
+
+// Handler for distinct leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_LEAF_DISTINCT
+#define HANDLE_MDNODE_LEAF_DISTINCT(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#endif
+
 // Handler for leaf nodes under MDNode.
 #ifndef HANDLE_MDNODE_LEAF
 #define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS)
@@ -80,7 +143,7 @@ HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder)
 HANDLE_MDNODE_BRANCH(MDNode)
 HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation)
-HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(DIExpression)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariableExpression)
 HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode)
@@ -93,7 +156,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIDerivedType)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICompositeType)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubroutineType)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFile)
-HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit)
+HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(DICompileUnit)
 HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram)
 HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase)
@@ -114,7 +177,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
-HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIArgList)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(DIArgList)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
 
@@ -123,7 +186,11 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
 #undef HANDLE_METADATA_BRANCH
 #undef HANDLE_MDNODE_LEAF
 #undef HANDLE_MDNODE_LEAF_UNIQUABLE
+#undef HANDLE_MDNODE_LEAF_UNIQUED
+#undef HANDLE_MDNODE_LEAF_DISTINCT
 #undef HANDLE_MDNODE_BRANCH
 #undef HANDLE_SPECIALIZED_MDNODE_LEAF
 #undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE
+#undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED
+#undef HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT
 #undef HANDLE_SPECIALIZED_MDNODE_BRANCH

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 5bce1eaa59a09..62c1c24b1bbd6 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -742,27 +742,29 @@ bool LLParser::parseNamedMetadata() {
     return true;
 
   NamedMDNode *NMD = M->getOrInsertNamedMetadata(Name);
-  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 &&
-                 Lex.getStrVal() == "DIArgList") {
-        return tokError("found DIArgList outside of function");
-      } else if (parseToken(lltok::exclaim, "Expected '!' here") ||
-                 parseMDNodeID(N)) {
-        return true;
-      }
-      NMD->addOperand(N);
-    } while (EatIfPresent(lltok::comma));
+
+  if (Lex.getKind() == lltok::rbrace) {
+    Lex.Lex();
+    return false;
+  }
+
+  do {
+    MDNode *N = nullptr;
+    // Parse uniqued MDNodes inline as a special case.
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS)                                      \
+  if (Lex.getKind() == lltok::MetadataVar && Lex.getStrVal() == #CLASS) {      \
+    if (parse##CLASS(N, /*IsDistinct=*/false))                                 \
+      return true;                                                             \
+    NMD->addOperand(N);                                                        \
+    continue;                                                                  \
+  }
+#include "llvm/IR/Metadata.def"
+    // Parse all other MDNodes as an MDNodeID.
+    if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDNodeID(N)) {
+      return true;
+    }
+    NMD->addOperand(N);
+  } while (EatIfPresent(lltok::comma));
 
   return parseToken(lltok::rbrace, "expected end of metadata node");
 }
@@ -782,9 +784,10 @@ bool LLParser::parseStandaloneMetadata() {
   if (Lex.getKind() == lltok::Type)
     return tokError("unexpected type in metadata definition");
 
+  auto DistinctLoc = Lex.getLoc();
   bool IsDistinct = EatIfPresent(lltok::kw_distinct);
   if (Lex.getKind() == lltok::MetadataVar) {
-    if (parseSpecializedMDNode(Init, IsDistinct))
+    if (parseSpecializedMDNode(Init, IsDistinct, DistinctLoc))
       return true;
   } else if (parseToken(lltok::exclaim, "Expected '!' here") ||
              parseMDTuple(Init, IsDistinct))
@@ -4332,12 +4335,25 @@ bool LLParser::parseMDField(StringRef Name, FieldTy &Result) {
   return parseMDField(Loc, Name, Result);
 }
 
-bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct) {
+bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct,
+                                      LocTy DistinctLoc) {
   assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
 
-#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS)                                  \
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS)                        \
   if (Lex.getStrVal() == #CLASS)                                               \
     return parse##CLASS(N, IsDistinct);
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(CLASS)                          \
+  if (Lex.getStrVal() == #CLASS) {                                             \
+    if (IsDistinct)                                                            \
+      return error(DistinctLoc, "'distinct' not allowed for !" #CLASS);        \
+    return parse##CLASS(N, IsDistinct);                                        \
+  }
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(CLASS)                         \
+  if (Lex.getStrVal() == #CLASS) {                                             \
+    if (!IsDistinct)                                                           \
+      return error(DistinctLoc, "missing 'distinct', required for !" #CLASS);  \
+    return parse##CLASS(N, IsDistinct);                                        \
+  }
 #include "llvm/IR/Metadata.def"
 
   return tokError("expected metadata type");
@@ -4683,9 +4699,6 @@ bool LLParser::parseDIFile(MDNode *&Result, bool IsDistinct) {
 ///                      globals: !4, imports: !5, macros: !6, dwoId: 0x0abcd,
 ///                      sysroot: "/", sdk: "MacOSX.sdk")
 bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) {
-  if (!IsDistinct)
-    return Lex.Error("missing 'distinct', required for !DICompileUnit");
-
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   REQUIRED(language, DwarfLangField, );                                        \
   REQUIRED(file, MDField, (/* AllowNull */ false));                            \
@@ -5009,6 +5022,7 @@ bool LLParser::parseDILabel(MDNode *&Result, bool IsDistinct) {
 /// parseDIExpression:
 ///   ::= !DIExpression(0, 7, -1)
 bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) {
+  assert(!IsDistinct && "DIExpression must not be distinct");
   assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
   Lex.Lex();
 
@@ -5050,17 +5064,18 @@ 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;
 }
 
 bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct) {
-  return parseDIArgList(Result, IsDistinct, nullptr);
+  return tokError("!DIArgList cannot appear outside of a function");
 }
 /// ParseDIArgList:
 ///   ::= !DIArgList(i32 7, i64 %0)
 bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct,
                               PerFunctionState *PFS) {
+  assert(!IsDistinct && "DIArgList must not be distinct");
   assert(PFS && "Expected valid function state");
   assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
   Lex.Lex();
@@ -5080,7 +5095,7 @@ bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct,
   if (parseToken(lltok::rparen, "expected ')' here"))
     return true;
 
-  Result = GET_OR_DISTINCT(DIArgList, (Context, Args));
+  Result = DIArgList::get(Context, Args);
   return false;
 }
 

diff  --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 15e2386b508de..4151e027fcf58 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -554,7 +554,7 @@ class MetadataLoader::MetadataLoaderImpl {
   }
 
   /// Upgrade the expression from previous versions.
-  Error upgradeDIExpression(uint64_t FromVersion,
+  Error upgradeDIExpression(uint64_t FromVersion, bool &IsDistinct,
                             MutableArrayRef<uint64_t> &Expr,
                             SmallVectorImpl<uint64_t> &Buffer) {
     auto N = Expr.size();
@@ -628,6 +628,9 @@ class MetadataLoader::MetadataLoaderImpl {
       LLVM_FALLTHROUGH;
     }
     case 3:
+      IsDistinct = false;
+      LLVM_FALLTHROUGH;
+    case 4:
       // Up-to-date!
       break;
     }
@@ -2002,11 +2005,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
 
     SmallVector<uint64_t, 6> Buffer;
-    if (Error Err = upgradeDIExpression(Version, Elts, Buffer))
+    if (Error Err = upgradeDIExpression(Version, IsDistinct, Elts, Buffer))
       return Err;
 
-    MetadataList.assignValue(
-        GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo);
+    if (IsDistinct)
+      return error("Invalid record");
+
+    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 fd77a8c80bb41..a92c11eb448ac 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1766,7 +1766,6 @@ void ModuleBitcodeWriter::writeDIFile(const DIFile *N,
 void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
                                              SmallVectorImpl<uint64_t> &Record,
                                              unsigned Abbrev) {
-  assert(N->isDistinct() && "Expected distinct compile units");
   Record.push_back(/* IsDistinct */ true);
   Record.push_back(N->getSourceLanguage());
   Record.push_back(VE.getMetadataOrNullID(N->getFile()));
@@ -2020,7 +2019,7 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
                                             SmallVectorImpl<uint64_t> &Record,
                                             unsigned Abbrev) {
   Record.reserve(N->getElements().size() + 1);
-  const uint64_t Version = 3 << 1;
+  const uint64_t Version = 4 << 1;
   Record.push_back((uint64_t)N->isDistinct() | Version);
   Record.append(N->elements_begin(), N->elements_end());
 
@@ -2166,6 +2165,20 @@ void ModuleBitcodeWriter::writeMetadataRecords(
     if (const MDNode *N = dyn_cast<MDNode>(MD)) {
       assert(N->isResolved() && "Expected forward references to be resolved");
 
+#ifndef NDEBUG
+      switch (N->getMetadataID()) {
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS)                                      \
+  case Metadata::CLASS##Kind:                                                  \
+    assert(!N->isDistinct() && "Expected non-distinct " #CLASS);               \
+    break;
+#define HANDLE_MDNODE_LEAF_DISTINCT(CLASS)                                     \
+  case Metadata::CLASS##Kind:                                                  \
+    assert(N->isDistinct() && "Expected distinct " #CLASS);                    \
+    break;
+#include "llvm/IR/Metadata.def"
+      }
+#endif
+
       switch (N->getMetadataID()) {
       default:
         llvm_unreachable("Invalid MDNode subclass");

diff  --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 1a04e1ca56a90..11cb1e140188d 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1184,6 +1184,7 @@ bool MIParser::parseStandaloneMDNode(MDNode *&Node) {
     if (parseMDNode(Node))
       return true;
   } else if (Token.is(MIToken::md_diexpr)) {
+    // FIXME: This should be driven off of the UNIQUED property in Metadata.def
     if (parseDIExpression(Node))
       return true;
   } else if (Token.is(MIToken::md_dilocation)) {
@@ -2327,6 +2328,7 @@ bool MIParser::parseMetadataOperand(MachineOperand &Dest) {
     if (parseMDNode(Node))
       return true;
   } else if (Token.is(MIToken::md_diexpr)) {
+    // FIXME: This should be driven off of the UNIQUED property in Metadata.def
     if (parseDIExpression(Node))
       return true;
   }

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index c7a46bd5fe253..78bc0240cbd8e 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1236,10 +1236,11 @@ void SlotTracker::CreateFunctionSlot(const Value *V) {
 void SlotTracker::CreateMetadataSlot(const MDNode *N) {
   assert(N && "Can't insert a null Value into SlotTracker!");
 
-  // Don't make slots for DIExpressions or DIArgLists. We just print them inline
-  // everywhere.
-  if (isa<DIExpression>(N) || isa<DIArgList>(N))
+  // Don't make slots for uniqued nodes. We just print them inline everywhere.
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS)                                      \
+  if (isa<CLASS>(N))                                                           \
     return;
+#include "llvm/IR/Metadata.def"
 
   unsigned DestSlot = mdnNext;
   if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
@@ -2332,10 +2333,7 @@ static void writeDIExpression(raw_ostream &Out, const DIExpression *N,
 }
 
 static void writeDIArgList(raw_ostream &Out, const DIArgList *N,
-                           AsmWriterContext &WriterCtx,
-                           bool FromValue = false) {
-  assert(FromValue &&
-         "Unexpected DIArgList metadata outside of value argument");
+                           AsmWriterContext &WriterCtx) {
   Out << "!DIArgList(";
   FieldSeparator FS;
   MDFieldPrinter Printer(Out, WriterCtx);
@@ -2486,16 +2484,16 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
 static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
                                    AsmWriterContext &WriterCtx,
                                    bool FromValue) {
-  // Write DIExpressions and DIArgLists inline when used as a value. Improves
-  // readability of debug info intrinsics.
-  if (const DIExpression *Expr = dyn_cast<DIExpression>(MD)) {
-    writeDIExpression(Out, Expr, WriterCtx);
-    return;
-  }
-  if (const DIArgList *ArgList = dyn_cast<DIArgList>(MD)) {
-    writeDIArgList(Out, ArgList, WriterCtx, FromValue);
-    return;
+  assert((FromValue || !(isa<LocalAsMetadata>(MD) || isa<DIArgList>(MD))) &&
+         "Unexpected function-local metadata outside of value argument");
+
+  // Write uniqued MDNodes inline when used as a value.
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS)                                      \
+  if (const CLASS *N = dyn_cast<CLASS>(MD)) {                                  \
+    write##CLASS(Out, N, WriterCtx);                                           \
+    return;                                                                    \
   }
+#include "llvm/IR/Metadata.def"
 
   if (const MDNode *N = dyn_cast<MDNode>(MD)) {
     std::unique_ptr<SlotTracker> MachineStorage;
@@ -2527,9 +2525,6 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
 
   auto *V = cast<ValueAsMetadata>(MD);
   assert(WriterCtx.TypePrinter && "TypePrinter required for metadata values");
-  assert((FromValue || !isa<LocalAsMetadata>(V)) &&
-         "Unexpected function-local metadata outside of value argument");
-
   WriterCtx.TypePrinter->print(V->getValue()->getType(), Out);
   Out << ' ';
   WriteAsOperandInternal(Out, V->getValue(), WriterCtx);
@@ -3416,15 +3411,17 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
     if (i)
       Out << ", ";
 
-    // Write DIExpressions inline.
+    // Write UNIQUED nodes inline.
     // FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose.
     MDNode *Op = NMD->getOperand(i);
     assert(!isa<DIArgList>(Op) &&
            "DIArgLists should not appear in NamedMDNodes");
-    if (auto *Expr = dyn_cast<DIExpression>(Op)) {
-      writeDIExpression(Out, Expr, AsmWriterContext::getEmpty());
-      continue;
-    }
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS)                                      \
+  if (auto *N = dyn_cast<CLASS>(Op)) {                                         \
+    write##CLASS(Out, N, AsmWriterContext::getEmpty());                        \
+    continue;                                                                  \
+  }
+#include "llvm/IR/Metadata.def"
 
     int Slot = Machine.getMetadataSlot(Op);
     if (Slot == -1)
@@ -4773,8 +4770,15 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
   WriteAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true);
 
   auto *N = dyn_cast<MDNode>(&MD);
-  if (OnlyAsOperand || !N || isa<DIExpression>(MD) || isa<DIArgList>(MD))
+  if (OnlyAsOperand || !N) {
+    return;
+  }
+  // Uniqued MDNodes are always treated as if OnlyAsOperand, as they are
+  // printed inline.
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS)                                      \
+  if (isa<CLASS>(MD))                                                          \
     return;
+#include "llvm/IR/Metadata.def"
 
   OS << " = ";
   WriteMDNodeBodyInternal(OS, N, *WriterCtx);

diff  --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 66d436520ee78..0b4db90eedf8b 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1071,6 +1071,7 @@ DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope,
 DIExpression *DIExpression::getImpl(LLVMContext &Context,
                                     ArrayRef<uint64_t> Elements,
                                     StorageType Storage, bool ShouldCreate) {
+  assert(Storage != Distinct && "DIExpression cannot be distinct");
   DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements));
   DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements));
 }
@@ -1641,6 +1642,7 @@ DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,
 DIArgList *DIArgList::getImpl(LLVMContext &Context,
                               ArrayRef<ValueAsMetadata *> Args,
                               StorageType Storage, bool ShouldCreate) {
+  assert(Storage != Distinct && "DIArgList cannot be distinct");
   DEFINE_GETIMPL_LOOKUP(DIArgList, (Args));
   DEFINE_GETIMPL_STORE_NO_OPS(DIArgList, (Args));
 }

diff  --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index ebbf382aea385..f60fbcf14ef12 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -65,6 +65,7 @@ LLVMContextImpl::~LLVMContextImpl() {
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
   for (auto *I : CLASS##s)                                                     \
     I->dropAllReferences();
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
 #include "llvm/IR/Metadata.def"
 
   // Also drop references that come from the Value bridges.
@@ -79,6 +80,7 @@ LLVMContextImpl::~LLVMContextImpl() {
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
   for (CLASS * I : CLASS##s)                                                   \
     delete I;
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
 #include "llvm/IR/Metadata.def"
 
   // Free the constants.

diff  --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index d84714d9b1f14..d39d3dca64a10 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1398,6 +1398,7 @@ class LLVMContextImpl {
 
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
   DenseSet<CLASS *, CLASS##Info> CLASS##s;
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
 #include "llvm/IR/Metadata.def"
 
   // Optional map for looking up composite types by identifier.

diff  --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 01bfff84f0c70..b817129cee354 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -672,6 +672,7 @@ MDNode *MDNode::replaceWithPermanentImpl() {
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
   case CLASS##Kind:                                                            \
     break;
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
 #include "llvm/IR/Metadata.def"
   }
 
@@ -812,6 +813,7 @@ MDNode *MDNode::uniquify() {
     dispatchRecalculateHash(SubclassThis, ShouldRecalculateHash);              \
     return uniquifyImpl(SubclassThis, getContext().pImpl->CLASS##s);           \
   }
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
 #include "llvm/IR/Metadata.def"
   }
 }
@@ -824,6 +826,7 @@ void MDNode::eraseFromStore() {
   case CLASS##Kind:                                                            \
     getContext().pImpl->CLASS##s.erase(cast<CLASS>(this));                     \
     break;
+#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
 #include "llvm/IR/Metadata.def"
   }
 }

diff  --git a/llvm/test/Assembler/invalid-diarglist-outside-function.ll b/llvm/test/Assembler/invalid-diarglist-outside-function.ll
new file mode 100644
index 0000000000000..351cd0bc7b40f
--- /dev/null
+++ b/llvm/test/Assembler/invalid-diarglist-outside-function.ll
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:6: error: !DIArgList cannot appear outside of a function
+!0 = !DIArgList()

diff  --git a/llvm/test/Assembler/invalid-diexpression-distinct.ll b/llvm/test/Assembler/invalid-diexpression-distinct.ll
new file mode 100644
index 0000000000000..96628e37479b2
--- /dev/null
+++ b/llvm/test/Assembler/invalid-diexpression-distinct.ll
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:6: error: 'distinct' not allowed for !DIExpression
+!0 = distinct !DIExpression()

diff  --git a/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll
new file mode 100644
index 0000000000000..d888e9a9eb827
--- /dev/null
+++ b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!8, !9}
+
+!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true)
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
+!2 = !DIFile(filename: "a.c", directory: "/")
+!3 = !{}
+!4 = !{!7}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: expr: !DIExpression()
+!6 = distinct !DIExpression()
+!7 = !DIGlobalVariableExpression(var: !0, expr: !6)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}

diff  --git a/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc
new file mode 100644
index 0000000000000..4be649dada479
Binary files /dev/null and b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc 
diff er


        


More information about the llvm-commits mailing list