]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - opencl/llvm.git/commitdiff
IR: Add 'distinct' MDNodes to bitcode and assembly
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Thu, 8 Jan 2015 22:38:29 +0000 (22:38 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Thu, 8 Jan 2015 22:38:29 +0000 (22:38 +0000)
Propagate whether `MDNode`s are 'distinct' through the other types of IR
(assembly and bitcode).  This adds the `distinct` keyword to assembly.

Currently, no one actually calls `MDNode::getDistinct()`, so these nodes
only get created for:

  - self-references, which are never uniqued, and
  - nodes whose operands are replaced that hit a uniquing collision.

The concept of distinct nodes is still not quite first-class, since
distinct-ness doesn't yet survive across `MapMetadata()`.

Part of PR22111.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225474 91177308-0d34-0410-b5e6-96231b3b80d8

20 files changed:
docs/LangRef.rst
include/llvm/Bitcode/LLVMBitCodes.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/AsmParser/LLToken.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/IR/AsmWriter.cpp
test/Assembler/distinct-mdnode.ll [new file with mode: 0644]
test/Transforms/Inline/noalias-calls.ll
test/Transforms/Inline/noalias-cs.ll
test/Transforms/Inline/noalias.ll
test/Transforms/Inline/noalias2.ll
test/Transforms/LoopUnroll/runtime-loop.ll
test/Transforms/LoopUnroll/unroll-pragmas-disabled.ll
test/Transforms/LoopVectorize/X86/already-vectorized.ll
test/Transforms/LoopVectorize/vectorize-once.ll
utils/emacs/llvm-mode.el
utils/vim/llvm.vim

index 5238fe90d30a836bcd9df1af09b967d751ed6453..0a1c7768d5a9dc76cd9302d0c037b6598a298b35 100644 (file)
@@ -2848,6 +2848,12 @@ their operand. For example:
 
     !{ !"test\00", i32 10}
 
+Metadata nodes that aren't uniqued use the ``distinct`` keyword. For example:
+
+.. code-block:: llvm
+
+    !0 = distinct !{!"test\00", i32 10}
+
 A :ref:`named metadata <namedmetadatastructure>` is a collection of
 metadata nodes, which can be looked up in the module symbol table. For
 example:
index a717cdde9ee818e2e65c2528cd299a94b931cc50..81544ea32d22be2ef74536f3380a2ff97ac282cf 100644 (file)
@@ -140,7 +140,7 @@ namespace bitc {
     METADATA_VALUE         = 2,   // VALUE:         [type num, value num]
     METADATA_NODE          = 3,   // NODE:          [n x md num]
     METADATA_NAME          = 4,   // STRING:        [values]
-    // 5 is unused.
+    METADATA_DISTINCT_NODE = 5,   // DISTINCT_NODE: [n x md num]
     METADATA_KIND          = 6,   // [n x [id, name]]
     // 7 is unused.
     METADATA_OLD_NODE      = 8,   // OLD_NODE:      [n x (type num, value num)]
index ca3c9e8b6f8611e7a98b8323980846f3bbb92551..de5db1a4093d02f64b1f73897c7238d40cd50312 100644 (file)
@@ -655,6 +655,9 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(x);
   KEYWORD(blockaddress);
 
+  // Metadata types.
+  KEYWORD(distinct);
+
   // Use-list order directives.
   KEYWORD(uselistorder);
   KEYWORD(uselistorder_bb);
index 232c580b88fce94becb7c2979ad96b9a5698aa90..bcb314dfbd77c32cbb9521b5b0ea08fdb3e23440 100644 (file)
@@ -618,8 +618,9 @@ bool LLParser::ParseStandaloneMetadata() {
   if (Lex.getKind() == lltok::Type)
     return TokError("unexpected type in metadata definition");
 
+  bool IsDistinct = EatIfPresent(lltok::kw_distinct);
   if (ParseToken(lltok::exclaim, "Expected '!' here") ||
-      ParseMDNode(Init))
+      ParseMDNode(Init, IsDistinct))
     return true;
 
   // See if this was forward referenced, if so, handle it.
@@ -2945,12 +2946,15 @@ bool LLParser::ParseGlobalValueVector(SmallVectorImpl<Constant *> &Elts) {
   return false;
 }
 
-bool LLParser::ParseMDNode(MDNode *&MD) {
+bool LLParser::ParseMDNode(MDNode *&MD, bool IsDistinct) {
   SmallVector<Metadata *, 16> Elts;
   if (ParseMDNodeVector(Elts))
     return true;
 
-  MD = MDNode::get(Context, Elts);
+  if (IsDistinct)
+    MD = MDNode::getDistinct(Context, Elts);
+  else
+    MD = MDNode::get(Context, Elts);
   return false;
 }
 
index d8d272b500dec40b0cab0c6b378f2961f4dca605..f1df5b8e54bd19a547bb4ccdee2e35ce3b37fa0a 100644 (file)
@@ -389,7 +389,7 @@ namespace llvm {
     bool ParseMetadataAsValue(Value *&V, PerFunctionState &PFS);
     bool ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS);
     bool ParseMetadata(Metadata *&MD, PerFunctionState *PFS);
-    bool ParseMDNode(MDNode *&MD);
+    bool ParseMDNode(MDNode *&MD, bool IsDistinct = false);
     bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &MDs);
     bool ParseInstructionMetadata(Instruction *Inst, PerFunctionState *PFS);
 
index a2111ca96e9b87ccdce333a24d0a3a698d96d728..4fb01824d9b5d87fc7c316d089230fae6bd6963c 100644 (file)
@@ -182,6 +182,9 @@ namespace lltok {
     kw_extractelement, kw_insertelement, kw_shufflevector,
     kw_extractvalue, kw_insertvalue, kw_blockaddress,
 
+    // Metadata types.
+    kw_distinct,
+
     // Use-list order directives.
     kw_uselistorder, kw_uselistorder_bb,
 
index 7c7eebde1df6167cd56370a3855d9e898313dce6..1792f8b8dd471c4371cc6826a3b4a3c12e973d34 100644 (file)
@@ -1106,6 +1106,7 @@ std::error_code BitcodeReader::ParseMetadata() {
     // Read a record.
     Record.clear();
     unsigned Code = Stream.readRecord(Entry.ID, Record);
+    bool IsDistinct = false;
     switch (Code) {
     default:  // Default behavior: ignore.
       break;
@@ -1196,12 +1197,17 @@ std::error_code BitcodeReader::ParseMetadata() {
           NextMDValueNo++);
       break;
     }
+    case bitc::METADATA_DISTINCT_NODE:
+      IsDistinct = true;
+      // fallthrough...
     case bitc::METADATA_NODE: {
       SmallVector<Metadata *, 8> Elts;
       Elts.reserve(Record.size());
       for (unsigned ID : Record)
         Elts.push_back(ID ? MDValueList.getValueFwdRef(ID - 1) : nullptr);
-      MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
+      MDValueList.AssignValue(IsDistinct ? MDNode::getDistinct(Context, Elts)
+                                         : MDNode::get(Context, Elts),
+                              NextMDValueNo++);
       break;
     }
     case bitc::METADATA_STRING: {
index 2eb67219c8a7a791a9480eb289dae35a1b3dc3cd..8152799bbcefe2c5cb0164eff929a12da74e4f2d 100644 (file)
@@ -773,7 +773,9 @@ static void WriteMDNode(const MDNode *N,
     assert(!isa<LocalAsMetadata>(MD) && "Unexpected function-local metadata");
     Record.push_back(VE.getMetadataID(MD) + 1);
   }
-  Stream.EmitRecord(bitc::METADATA_NODE, Record);
+  Stream.EmitRecord(N->isDistinct() ? bitc::METADATA_DISTINCT_NODE
+                                    : bitc::METADATA_NODE,
+                    Record);
   Record.clear();
 }
 
index 175e20f9794a69ad982c85968de2e35d1018faef..dc2c5934c2a19f7efee737c22425ec61a965e29d 100644 (file)
@@ -1253,6 +1253,8 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
                                     TypePrinting *TypePrinter,
                                     SlotTracker *Machine,
                                     const Module *Context) {
+  if (Node->isDistinct())
+    Out << "distinct ";
   Out << "!{";
   for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) {
     const Metadata *MD = Node->getOperand(mi);
diff --git a/test/Assembler/distinct-mdnode.ll b/test/Assembler/distinct-mdnode.ll
new file mode 100644 (file)
index 0000000..abd7aea
--- /dev/null
@@ -0,0 +1,28 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
+
+!0 = !{}
+!1 = !{}   ; This should merge with !0.
+!2 = !{!0}
+!3 = !{!0} ; This should merge with !2.
+!4 = distinct !{}
+!5 = distinct !{}
+!6 = distinct !{!0}
+!7 = distinct !{!0}
+!8 = distinct !{!8}
+!9 = distinct !{!9}
+!10 = !{!10} ; This should become distinct.
+
+; CHECK: !named = !{!0, !0, !1, !1, !2, !3, !4, !5, !6, !7, !8}
+; CHECK:      !0 = !{}
+; CHECK-NEXT: !1 = !{!0}
+; CHECK-NEXT: !2 = distinct !{}
+; CHECK-NEXT: !3 = distinct !{}
+; CHECK-NEXT: !4 = distinct !{!0}
+; CHECK-NEXT: !5 = distinct !{!0}
+; CHECK-NEXT: !6 = distinct !{!6}
+; CHECK-NEXT: !7 = distinct !{!7}
+; CHECK-NEXT: !8 = distinct !{!8}
+; CHECK-NOT:  !
index 85870f144d94652349b9ae4f5100c71557f4db56..c09d2a67329761a2cb03b5d93a3056776748a8c3 100644 (file)
@@ -36,9 +36,9 @@ attributes #0 = { nounwind }
 attributes #1 = { nounwind uwtable }
 
 ; CHECK: !0 = !{!1}
-; CHECK: !1 = !{!1, !2, !"hello: %c"}
-; CHECK: !2 = !{!2, !"hello"}
+; CHECK: !1 = distinct !{!1, !2, !"hello: %c"}
+; CHECK: !2 = distinct !{!2, !"hello"}
 ; CHECK: !3 = !{!4}
-; CHECK: !4 = !{!4, !2, !"hello: %a"}
+; CHECK: !4 = distinct !{!4, !2, !"hello: %a"}
 ; CHECK: !5 = !{!4, !1}
 
index 44bce57b744a6f7c96e9e117b1187964c26de5e0..da5ddd64ed065d52bbe8cd121231cd320ccdac76 100644 (file)
@@ -47,36 +47,36 @@ entry:
 attributes #0 = { nounwind uwtable }
 
 !0 = !{!1}
-!1 = !{!1, !2, !"hello: %a"}
-!2 = !{!2, !"hello"}
+!1 = distinct !{!1, !2, !"hello: %a"}
+!2 = distinct !{!2, !"hello"}
 !3 = !{!4, !6}
-!4 = !{!4, !5, !"hello2: %a"}
-!5 = !{!5, !"hello2"}
-!6 = !{!6, !5, !"hello2: %b"}
+!4 = distinct !{!4, !5, !"hello2: %a"}
+!5 = distinct !{!5, !"hello2"}
+!6 = distinct !{!6, !5, !"hello2: %b"}
 !7 = !{!4}
 !8 = !{!6}
 
 ; CHECK: !0 = !{!1, !3}
-; CHECK: !1 = !{!1, !2, !"hello2: %a"}
-; CHECK: !2 = !{!2, !"hello2"}
-; CHECK: !3 = !{!3, !2, !"hello2: %b"}
+; CHECK: !1 = distinct !{!1, !2, !"hello2: %a"}
+; CHECK: !2 = distinct !{!2, !"hello2"}
+; CHECK: !3 = distinct !{!3, !2, !"hello2: %b"}
 ; CHECK: !4 = !{!1}
 ; CHECK: !5 = !{!3}
 ; CHECK: !6 = !{!7, !9, !10}
-; CHECK: !7 = !{!7, !8, !"hello2: %a"}
-; CHECK: !8 = !{!8, !"hello2"}
-; CHECK: !9 = !{!9, !8, !"hello2: %b"}
-; CHECK: !10 = !{!10, !11, !"hello: %a"}
-; CHECK: !11 = !{!11, !"hello"}
+; CHECK: !7 = distinct !{!7, !8, !"hello2: %a"}
+; CHECK: !8 = distinct !{!8, !"hello2"}
+; CHECK: !9 = distinct !{!9, !8, !"hello2: %b"}
+; CHECK: !10 = distinct !{!10, !11, !"hello: %a"}
+; CHECK: !11 = distinct !{!11, !"hello"}
 ; CHECK: !12 = !{!7}
 ; CHECK: !13 = !{!9, !10}
 ; CHECK: !14 = !{!9}
 ; CHECK: !15 = !{!7, !10}
 ; CHECK: !16 = !{!10}
 ; CHECK: !17 = !{!18, !20}
-; CHECK: !18 = !{!18, !19, !"hello2: %a"}
-; CHECK: !19 = !{!19, !"hello2"}
-; CHECK: !20 = !{!20, !19, !"hello2: %b"}
+; CHECK: !18 = distinct !{!18, !19, !"hello2: %a"}
+; CHECK: !19 = distinct !{!19, !"hello2"}
+; CHECK: !20 = distinct !{!20, !19, !"hello2: %b"}
 ; CHECK: !21 = !{!18, !10}
 ; CHECK: !22 = !{!20}
 ; CHECK: !23 = !{!20, !10}
index 76e4508417e26da3f3dd0e1c6be7b87b06625657..674da1e2efbb32f9087ba463c28a012626a507f0 100644 (file)
@@ -65,12 +65,12 @@ entry:
 attributes #0 = { nounwind uwtable }
 
 ; CHECK: !0 = !{!1}
-; CHECK: !1 = !{!1, !2, !"hello: %a"}
-; CHECK: !2 = !{!2, !"hello"}
+; CHECK: !1 = distinct !{!1, !2, !"hello: %a"}
+; CHECK: !2 = distinct !{!2, !"hello"}
 ; CHECK: !3 = !{!4, !6}
-; CHECK: !4 = !{!4, !5, !"hello2: %a"}
-; CHECK: !5 = !{!5, !"hello2"}
-; CHECK: !6 = !{!6, !5, !"hello2: %b"}
+; CHECK: !4 = distinct !{!4, !5, !"hello2: %a"}
+; CHECK: !5 = distinct !{!5, !"hello2"}
+; CHECK: !6 = distinct !{!6, !5, !"hello2: %b"}
 ; CHECK: !7 = !{!4}
 ; CHECK: !8 = !{!6}
 
index b2734b2401907f6adc94d065116e8481a4ddfe60..9c8f8e22d388f4291caa034c1a8b83d342763129 100644 (file)
@@ -72,24 +72,24 @@ entry:
 ; CHECK: }
 
 ; CHECK: !0 = !{!1}
-; CHECK: !1 = !{!1, !2, !"hello: %c"}
-; CHECK: !2 = !{!2, !"hello"}
+; CHECK: !1 = distinct !{!1, !2, !"hello: %c"}
+; CHECK: !2 = distinct !{!2, !"hello"}
 ; CHECK: !3 = !{!4}
-; CHECK: !4 = !{!4, !2, !"hello: %a"}
+; CHECK: !4 = distinct !{!4, !2, !"hello: %a"}
 ; CHECK: !5 = !{!6, !8}
-; CHECK: !6 = !{!6, !7, !"hello: %c"}
-; CHECK: !7 = !{!7, !"hello"}
-; CHECK: !8 = !{!8, !9, !"foo: %c"}
-; CHECK: !9 = !{!9, !"foo"}
+; CHECK: !6 = distinct !{!6, !7, !"hello: %c"}
+; CHECK: !7 = distinct !{!7, !"hello"}
+; CHECK: !8 = distinct !{!8, !9, !"foo: %c"}
+; CHECK: !9 = distinct !{!9, !"foo"}
 ; CHECK: !10 = !{!11, !12}
-; CHECK: !11 = !{!11, !7, !"hello: %a"}
-; CHECK: !12 = !{!12, !9, !"foo: %a"}
+; CHECK: !11 = distinct !{!11, !7, !"hello: %a"}
+; CHECK: !12 = distinct !{!12, !9, !"foo: %a"}
 ; CHECK: !13 = !{!8}
 ; CHECK: !14 = !{!12}
 ; CHECK: !15 = !{!16, !18}
-; CHECK: !16 = !{!16, !17, !"hello2: %a"}
-; CHECK: !17 = !{!17, !"hello2"}
-; CHECK: !18 = !{!18, !17, !"hello2: %b"}
+; CHECK: !16 = distinct !{!16, !17, !"hello2: %a"}
+; CHECK: !17 = distinct !{!17, !"hello2"}
+; CHECK: !18 = distinct !{!18, !17, !"hello2: %b"}
 ; CHECK: !19 = !{!16}
 ; CHECK: !20 = !{!18}
 
index 925c3e2a360617b04660c9518899a29245aa51a1..3a8777bb14730ff4fbe3cb6459988df046b2f497 100644 (file)
@@ -115,6 +115,6 @@ for.end:                                          ; preds = %for.cond.for.end_cr
   ret i16 %res.0.lcssa
 }
 
-; CHECK: !0 = !{!0, !1}
+; CHECK: !0 = distinct !{!0, !1}
 ; CHECK: !1 = !{!"llvm.loop.unroll.disable"}
 
index 748a49e8ff4a36b7150e4e556cf5fd565abe52b7..4f934a688be8dd5e62dff3a070b38f053f28a706 100644 (file)
@@ -138,12 +138,12 @@ for.inc5.1:                                       ; preds = %for.body3.1
 !10 = !{!"llvm.loop.unroll.count", i32 2}
 
 
-; CHECK: ![[LOOP_1]] = !{![[LOOP_1]], ![[VEC_ENABLE:.*]], ![[WIDTH_8:.*]], ![[UNROLL_DISABLE:.*]]}
+; CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[VEC_ENABLE:.*]], ![[WIDTH_8:.*]], ![[UNROLL_DISABLE:.*]]}
 ; CHECK: ![[VEC_ENABLE]] = !{!"llvm.loop.vectorize.enable", i1 true}
 ; CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8}
 ; CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
-; CHECK: ![[LOOP_2]] = !{![[LOOP_2]], ![[UNROLL_FULL:.*]]}
+; CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNROLL_FULL:.*]]}
 ; CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"}
-; CHECK: ![[LOOP_3]] = !{![[LOOP_3]], ![[UNROLL_DISABLE:.*]]}
-; CHECK: ![[LOOP_4]] = !{![[LOOP_4]], ![[UNROLL_DISABLE:.*]]}
-; CHECK: ![[LOOP_5]] = !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]]}
+; CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_DISABLE:.*]]}
+; CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_DISABLE:.*]]}
+; CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]]}
index f3191c86f4a9c578e9fb74f42814e2c348b637b1..29d74a0645e8da4474ea5c7ec07b4b01360a0184 100644 (file)
@@ -39,8 +39,8 @@ for.end:                                          ; preds = %for.body
 }
 
 ; Now, we check for the Hint metadata
-; CHECK: [[vect]] = !{[[vect]], [[width:![0-9]+]], [[unroll:![0-9]+]]}
+; CHECK: [[vect]] = distinct !{[[vect]], [[width:![0-9]+]], [[unroll:![0-9]+]]}
 ; CHECK: [[width]] = !{!"llvm.loop.vectorize.width", i32 1}
 ; CHECK: [[unroll]] = !{!"llvm.loop.interleave.count", i32 1}
-; CHECK: [[scalar]] = !{[[scalar]], [[width]], [[unroll]]}
+; CHECK: [[scalar]] = distinct !{[[scalar]], [[width]], [[unroll]]}
 
index 30fdd8f315877fab30826f66d317d321228d7b37..a9b2a53f74b313ef92827236a368f7bcf24d3b56 100644 (file)
@@ -68,10 +68,10 @@ _ZSt10accumulateIPiiET0_T_S2_S1_.exit:            ; preds = %for.body.i, %entry
 
 attributes #0 = { nounwind readonly ssp uwtable "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "realign-stack" "relocation-model"="pic" "ssp-buffers-size"="8" }
 
-; CHECK: !0 = !{!0, !1, !2}
+; CHECK: !0 = distinct !{!0, !1, !2}
 ; CHECK: !1 = !{!"llvm.loop.vectorize.width", i32 1}
 ; CHECK: !2 = !{!"llvm.loop.interleave.count", i32 1}
-; CHECK: !3 = !{!3, !1, !2}
+; CHECK: !3 = distinct !{!3, !1, !2}
 
 !0 = !{!0, !1}
 !1 = !{!"llvm.loop.vectorize.width", i32 1}
index 6758bdfe870ed0ddcfe5bdbc306c51148cbb3bff..6d8395cc111b86c4f86d67f59883e06061ef88b1 100644 (file)
@@ -53,6 +53,8 @@
    `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face)
    ;; Aggregate ops
    `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face)
+   ;; Metadata types
+   `(,(regexp-opt '("distinct") 'words) . font-lock-keyword-face)
    ;; Use-list order directives
    `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face)
 
index 7d413dd2ec41b1b553ff52b0f82e7b050191b4aa..23a34b513365822d32096adca148cee1f45189ce 100644 (file)
@@ -41,7 +41,7 @@ syn keyword llvmKeyword alignstack alwaysinline appending arm_aapcs_vfpcc
 syn keyword llvmKeyword arm_aapcscc arm_apcscc asm atomic available_externally
 syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common
 syn keyword llvmKeyword constant datalayout declare default define deplibs
-syn keyword llvmKeyword dllexport dllimport except extern_weak external
+syn keyword llvmKeyword distinct dllexport dllimport except extern_weak external
 syn keyword llvmKeyword externally_initialized fastcc filter gc global hidden
 syn keyword llvmKeyword initialexec inlinehint inreg intel_ocl_bicc inteldialect
 syn keyword llvmKeyword internal linkonce linkonce_odr localdynamic localexec