mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
IR: Add 'distinct' MDNodes to bitcode and assembly
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. llvm-svn: 225474
This commit is contained in:
parent
22ffa9b291
commit
090a19bd3c
@ -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:
|
||||
|
@ -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)]
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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: {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
28
llvm/test/Assembler/distinct-mdnode.ll
Normal file
28
llvm/test/Assembler/distinct-mdnode.ll
Normal file
@ -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: !
|
@ -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}
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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"}
|
||||
|
||||
|
@ -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:.*]]}
|
||||
|
@ -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]]}
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user